Снижение точности в парном разряде в R - PullRequest
0 голосов
/ 28 мая 2018

Я ищу способ последовательно игнорировать небольшие различия между числами с плавающей запятой в R (это числа с плавающей запятой двойной точности согласно IEC 60559), используя базовые инструменты R и не прибегая к C или C ++.Другими словами, я хотел бы «округлить» значение и часть чисел с плавающей запятой двойной точности так, чтобы такие вещи возвращали ИСТИНА вместо ЛОЖЬ:

1.45 - .55 == 2.45 - 1.55
## [1] FALSE

Что-то вроде:

round_significand(1.45 - .55, bits=48) == round_significand(2.45 - 1.55, bits=48)
## [1] TRUE

Простое round не работает, потому что уровень, до которого нам нужно округлить, зависит от величины числа.

data.table делает что-то подобное внутри, начиная с ?setNumericRounding:

Компьютеры не могут точно представлять некоторые числа с плавающей запятой (например, 0,6), используя базу 2. Это приводит к неожиданному поведению при объединении или группировании столбцов типа «числовой»;то есть «двойной», см. пример ниже.В тех случаях, когда это нежелательно, data.table позволяет округлять такие данные примерно до 11 sf, что во многих случаях является большим количеством цифр.Это достигается путем округления последних 2 байтов от значения.Другими возможными значениями являются округление до 1 байта или отсутствие округления (полная точность, по умолчанию).

Я работаю над реализацией взлома, которая масштабирует все до десятичного числа x, такого, что floor(log10(x)) == 1 и округляет, например:

rnd_sig <- function(x, precision=10) {
  exp <- floor(log10(abs(x)))
  round(x * 10 ^ (-exp), precision) / 10 ^ (-exp)
}

, но я не знаю достаточно о числах с плавающей запятой, чтобы быть уверенным, что это безопасно (или когда это безопасно, и нет).

Ответы [ 3 ]

0 голосов
/ 30 мая 2018

Нет общего ответа о том, насколько результат, вычисленный с плавающей запятой, может отличаться от точного математического результата.В общем, конечная ошибка последовательности вычислений может варьироваться от нуля до бесконечности (и может также давать результаты не числа, когда есть точно математический результат, или может давать числовой результат, когда нет определенного математического результата).Следовательно, определение допустимого отклонения для классификации того, равны ли два вычисленных результата или нет, требует решения для конкретной задачи: необходимо проанализировать вычисления и числа, участвующие в конкретной проблеме, и определить границы возможной ошибки или взвесить конкретные преимущества и недостатки.принятия неправильных классификаций.

Изучение ошибок, которые приводят к числовым вычислениям: численный анализ .Это широкая область, к которой обращаются многие книг .Простого ответа не существует.

В простых ситуациях может оказаться возможным определить границы ошибок и показать, что эти границы меньше различий между результатами, о которых известно, что они различны.Другими словами, учитывая вычисление, которое в идеале должно было бы давать результаты a и b , но на самом деле дает a и b, возможно, можно показать, что существует некоторая граница E при такой ошибке, что | a - b |<<em> E тогда и только тогда, когда a равно b .Однако невозможно ответить на этот вопрос, не зная, какие вычисления выполняются, и, возможно, не зная, какова область входных значений.

0 голосов
/ 03 июня 2018

Одним из возможных решений является использование signif, функции, связанной с round и включенной в тот же файл справки.Файл справки из ?signif говорит, что

означает округление значений в первом аргументе до указанного числа значащих цифр.

Принимая во внимание

округляет значения в первом аргументе до указанного числа десятичных знаков (по умолчанию 0).

Таким образом, похоже, что signif может быть более тесно связано с вашей проблемой.

0 голосов
/ 28 мая 2018

Предупреждение: это не прямой ответ на вопрос.

Я считаю полезными следующие две функции.Они позволяют мне сравнивать двойные значения с заданной степенью точности.

are.equal <- function(x, y, tol = .Machine$double.eps^0.5) abs(x - y) < tol
is.zero <- function(x, tol = .Machine$double.eps^0.5) abs(x) < tol

are.equal(1.45 - 0.55, 2.45 - 1.55)
#[1] TRUE

is.zero(1.45 - 0.55 - (2.45 - 1.55))
#[1] TRUE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...