Почему R вставляет больше десятичных знаков, чем было округлено, но только иногда? - PullRequest
0 голосов
/ 13 декабря 2018

Я знаю, что числа с плавающей запятой странные, но я раньше не сталкивался с такой проблемой.У меня есть вектор чисел в R. Я вижу, сколько их больше нуля, и я беру среднее из этого, чтобы получить пропорцию выше нуля.Я присваиваю номер объекту после его округления.Когда я иду вставить его, цифры возвращаются.Я бы dput вектор, но это слишком долго для этого, но вот head и str:

> head(x)
[1] 0.1616631 0.2117250 0.1782197 0.1791657 0.2067048 0.2042075
> str(x)
 num [1:4000] 0.162 0.212 0.178 0.179 0.207 ...

Теперь вот где я сталкиваюсь с проблемами:

> y <- round(mean(x > 0) * 100, 1)

> y
[1] 99.7

> str(y)
 num 99.7

> paste(100 - y, "is the inverse")
[1] "0.299999999999997 is the inverse"

Но это не будет вести себя так же, если я не вычтю из 100:

> paste(y, "is it pasted")
[1] "99.7 is it pasted"

Я знаю, что мог бы поставить round прямо в команду paste или использовать sprintf, и я знаю, как числа с плавающей точкой представлены в R, но Мне особенно интересно , почему это происходит для первой ситуации, а не для второй ?Я также не могу получить воспроизводимый пример, потому что я не могу заставить случайно сгенерированный вектор вести себя таким же образом.

1 Ответ

0 голосов
/ 13 декабря 2018

Есть ошибка округления, но в этом случае R. не справляется с этим хорошо.

Любое представление чисел с плавающей точкой в ​​R выполняется как double, что означает 53 бита точности, приблизительно 16 цифр,Это также относится к 99.7, вы можете увидеть, где он ломается:

print(99.7, digits=16) # works fine
print(99.7, digits=17) # Adds a 3 at the end on my platform

Это всегда будет предел, о котором вас предупреждают при указании его в печати (в документах).

Но когда вы выполняете вычисления, любая ошибка округления остается абсолютной, то есть ожидаемое значение .3 имеет абсолютную ошибку, которая столь же велика, но равна относительно 300раз больше.Следовательно, он «терпит неудачу» с менее значимыми цифрами:

print(100-99.7, digits=14) # works fine
print(100-99.7, digits=15) # Allready rounding error at digits=15

Теперь paste передает любое число в функцию as.character, которая (в этом случае, к сожалению) не смотрит ни на какие опции, которые вы установиливсегда используется значение по умолчанию 15 значащих цифр.

Чтобы решить эту проблему, вы можете использовать format, чтобы указать желаемое количество цифр:

paste(format(100 - y, digits=14), "is the inverse")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...