Точность сравнения с плавающей запятой

Учитывая 3 числа с плавающей запятой IEEE-754 a, b, c, которые не являются +/-INF и не NaN, и a ‹ b, можно ли предположить, что a - c ‹ b - c? Или вы можете привести пример, когда это неправильно?


person user16367    schedule 16.11.2012    source источник
comment
Обязательная ссылка: docs.oracle.com/cd/E19957-01 /806-3568/ncg_goldberg.html   -  person Robᵩ    schedule 16.11.2012


Ответы (1)


Предположим, что a равно приблизительно 0,00000000000000001, b приблизительно равно 0,000000000000000002, а c равно 1. Тогда a c и b c будут равны 1.

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


Отредактировано для добавления объяснения:

Если мы проигнорируем денормализованные значения, нечисловые значения, бесконечности и т. д. и просто сосредоточимся на значение двойной точности с плавающей запятой IEEE 754, чтобы иметь что-то конкретное, на что можно было бы посмотреть, то с точки зрения двоичного представления значение с плавающей запятой состоит из знакового бита s (0 для положительного, 1 для отрицательного), одиннадцатибитный показатель степени e (со смещением 1023, так что e=0 означает 21023< /sup> и e=1023 означает 20, т. е. 1), и 52-битный мантиссанд с фиксированной точкой m (представляющий 52 разряда за двоичной точкой, поэтому она находится в диапазоне от [0,1) с конечной точностью). Таким образом, фактическое значение представления равно (1)s (1 + m) 2e 1023.

Поскольку мантиссса имеет фиксированную точку и имеет фиксированное количество битов, точность очень конечна. Значение, подобное 1.000000000000000001, и значение, подобное 1.000000000000000002, идентичны для очень многих знаков после запятой и большего количества знаков, чем может содержать мантиссанда с двойной точностью.

Когда вы выполняете сложение или вычитание между очень большим числом и очень маленьким числом (относительно друг друга: в нашем примере 1 является «очень большим»; в качестве альтернативы мы могли бы использовать 1 как очень маленькое значение и выбрать очень большое число). значение 10000000000000000), результирующий показатель степени будет почти полностью определяться очень большим числом, а значение очень маленького числа должно быть соответствующим образом масштабировано. В нашем случае оно делится примерно на 1017; так просто исчезает. Значение не содержит достаточно битов, чтобы различить это.

person ruakh    schedule 16.11.2012
comment
это было быстро спасибо :) даже не могу принять это еще. также, возможно, вы можете добавить быстрое объяснение, почему это происходит - person user16367; 16.11.2012
comment
Диапазон экспоненты IEEE 754 64-битной двоичной с плавающей запятой составляет от -1022 (не -1024) до 1023. (Кроме того, дробная часть правильно называется мантиссом, а не мантиссом.) - person Eric Postpischil; 18.11.2012
comment
@EricPostpischil: Спасибо. Я написал свое объяснение слишком быстро, и помимо того, что вы указали, в нем есть и другие не совсем правильные вещи. (Например, я использовал своего рода логический знак 1 или -1 и логическую экспоненту, которая представляет собой целое число со знаком, но, возможно, было бы более разумно использовать фактический бит знака 0 или 1 и побитовую экспоненту, которая у вас есть. чтобы вычесть 1023 из.) Ах, хорошо. Я думаю, что этого достаточно для целей этого вопроса, но я подумаю, как его можно сделать более точным. (Или не стесняйтесь редактировать его самостоятельно.) - person ruakh; 18.11.2012