Объясните 1 - 3 * (4/3 - 1) = 2,2204e-16 в Matlab

Я пытаюсь понять числа двойной точности в Matlab. . Почему это 1 - 3 * (4/3 - 1) не равно нулю?


person hhh    schedule 12.03.2013    source источник
comment
Плавающая точка не точно представляет десятичные числа. См. раздел Что должен знать каждый программист об арифметике с плавающей запятой.   -  person Robert Harvey    schedule 12.03.2013
comment
Мое необоснованное предположение состоит в том, что из-за основного представления двойников оно рассчитывается как 2,22044604925031E-16.   -  person lzcd    schedule 12.03.2013
comment
также см. eps в справке Matlab   -  person Sridutt    schedule 12.03.2013
comment
Связанный вопрос: Это Ошибка матлаба? У вас такая же проблема?   -  person Eitan T    schedule 12.03.2013
comment
Возможно, вам будет интересно прочитать мою статью «Ответ один (если вы не используете числа с плавающей запятой)»: exploringbinary.com/   -  person Rick Regan    schedule 12.03.2013


Ответы (3)


Вещественное число 4/3 не может быть представлено в формате двойной точности (или в любом другом двоичном формате с плавающей запятой), потому что оно не является двоично-рациональным. Таким образом, когда вы вычисляете 4/3 в MATLAB, полученное значение округляется до ближайшего представимого числа с двойной точностью, а именно:

1.3333333333333332593184650249895639717578887939453125

Вычитание 1 из этого значения является точным (известная теорема анализа ошибок FP гласит, что вычитание чисел, отличающихся друг от друга в два раза, является точным), поэтому результат 4/3 - 1 таков:

0.3333333333333332593184650249895639717578887939453125

Бывает, что результат умножения этого числа на три тоже точно представим:

0.9999999999999997779553950749686919152736663818359375

Наконец, вычитание из 1,0 также является точным (согласно теореме, на которую я ссылался ранее):

0.0000000000000002220446049250313080847263336181640625

Таким образом, в ваших вычислениях имеется только один источник ошибки округления, поскольку 4/3 не может быть представлено как двойное число, а конечным результатом вычисления является просто эта начальная ошибка, перенесенная вперед.

person Stephen Canon    schedule 12.03.2013

Выполнение этого на научном калькуляторе - log2(2.2204e-16) - дает (почти) ровно -52. Другими словами, Matlab хранит 52 бита точности в double, еще 5 бит для показателя степени (4 + знак) и один для знака мантиссы. Это соответствует реализации IEEE 754: 53 бита для мантиссы (52 + знак) и 5 ​​для экспоненты. Все хорошо! Как всегда, вы должны проверить, достаточно ли близки два числа с плавающей запятой, а не точно ли они равны. Соответствующий пример в Matlab будет выглядеть так:

if abs(x - y) < 1e-15
      % Some code to execute when x and y are approximately equal
else
      % Some other code
end

Заявление о соответствии стандарту IEEE 754 взято из статьи в Википедии.

person Austin Mullins    schedule 12.03.2013
comment
Вау, мод увидел мой ответ. Это впервые. - person Austin Mullins; 12.03.2013
comment
Кроме того, я отредактировал ответ выше, включив функцию abs. Очень важный! - person Austin Mullins; 12.03.2013

Проблемы начинаются с вычисления 4/3. Точный ответ не может быть представлен ни конечным числом десятичных цифр, ни конечным числом битов. Результат будет сохранен как 4/3+r, где r — небольшое число со знаком абсолютного значения, представляющее разницу между реальным значением 4/3 и ближайшим 64-битным двоичным числом с плавающей запятой IEEE 754 к 4/3, ошибке округления.

Вычитание 1 дает 1/3+r. Умножение на 3 дает 1+3r. Вычитание из 1 дает -3r.

Конечный результат в -3 раза превышает ошибку округления в исходном представлении 4/3.

person Patricia Shanahan    schedule 12.03.2013