MPFR - потеря точности после добавления - PullRequest
0 голосов
/ 16 июня 2020

Во-первых, извините, если этот вопрос выглядит «глупо», потому что я новичок в MPFR, LOL.

У меня есть две mpfr_t переменных с точностью 1024, и они имеют значение 0,2 и В них хранится 0,06.

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

Это странно, потому что библиотека MPFR должна поддерживать точность (не так ли?).

Не могли бы вы помочь мне с этим? Большое спасибо заранее.

1 Ответ

0 голосов
/ 16 июня 2020

Числа MPFR представлены в двоичном формате (основание 2). В этой системе единственные числа, которые могут быть представлены точно, имеют форму N · 2 k , где N и k - целые числа. Ни 0,2 = 1/5, ни 0,06 = 3/50 не имеют такой формы, поэтому они аппроксимируются с небольшой ошибкой. Когда вы добавляете эти переменные, вы видите последствия этой ошибки (также может быть другая ошибка в операции сложения, поскольку в двоичном формате эти числа имеют много ненулевых цифр, в отличие от десятичных).

Это то же самое проблема, как описано в: Математика с плавающей запятой не работает?

EDIT:

Чтобы ответить на вопрос в комментарии «Есть ли способ чтобы избежать этой ситуации? », нет, на практике нет никакого способа избежать этой ситуации, кроме очень специфических c случаев. Например, если все ваши числа (входные данные и результаты каждой промежуточной операции) являются десятичными числами, которые можно представить с помощью достаточно небольшого количества цифр, вы можете использовать десятичную арифметику c (но MPFR не может этого сделать). В некоторых случаях могут помочь системы компьютерной алгебры. Также есть iRRAM ... Я вернусь к этому позже.

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

  • Для вывода выберите количество отображаемых цифр так, чтобы ошибка была меньше веса последнего отображаемого di git.
  • Для прерывистых функций (например, проверка на равенство, floor, ceil): если расстояние между вычисленным значением и точкой разрыва меньше максимальной ошибки, предположим, что фактическое значение равно точке разрыва. Обратите внимание, что это всего лишь эвристический c, но если он не работает (это может остаться незамеченным и, вероятно, сделает вашу оценку недействительной), это означает, что вы не выполнили свои вычисления с достаточной точностью.

Примечание: MPFR не сделает этого за вас. Но вы можете написать код, учитывающий эти правила.

Пакет iRRAM, основанный на MPFR, может точно отслеживать ошибку (например, с помощью арифметики интервала c) и автоматически повторить все вычисления с более высокой точностью, если обнаружит, что точность слишком низкая. Однако, если какой-то математический результат является точкой разрыва, iRRAM не поможет. В частности, он не может обеспечить строгий тест на равенство.

Наконец, я предлагаю вам взглянуть на статью Голдберга Что каждый компьютерный ученый должен знать об арифметике с плавающей запятой c, в частности понятие аннулирование .

...