Двойной расчет с нечетным результатом

У меня есть 2 числа, сохраненные как Double, 1.4300 и 1.4350. Когда я вычитаю 1,4350 - 1,4300, это дает мне результат: 0,0050000000000001155. Почему он добавляет 1155 в конец и как решить эту проблему, чтобы он возвращал 0,005 или 0,0050? Я не уверен, что округление будет работать, так как я работаю с 2 и 4 десятичными числами.


person Roger    schedule 24.11.2011    source источник


Ответы (3)


О, я люблю это... это вызвано неточностью в двойном представлении, и арифметика с плавающей запятой полна этого. Это часто вызвано повторяющимися числами в двоичном формате (т. е. представлением с плавающей запятой с основанием 2). Например, в десятичном виде 1/3 = 0,3333'. В двоичном формате 1/10 — это повторяющееся число, а это значит, что его невозможно точно представить. Попробуйте это: 1 - 0,1 - 0,1 - 0,1 - 0,1. Вы не получите 0,6 :-)

Чтобы решить эту проблему, используйте BigDecimal (предпочтительно) или манипулируйте двойным значением, сначала умножив его примерно на 10000, затем округлив, а затем снова разделив (менее чисто).

Хороший вопрос... в прошлом он вызывал огромные проблемы. Ракеты пролетают мимо целей, спутники падают после запуска и т. д. Поищите в Интернете, вы будете поражены!

person Jaco Van Niekerk    schedule 24.11.2011
comment
Вы серьезно насчёт ракет и спутников? Или это был сарказм? - person medopal; 24.11.2011
comment
ima.umn.edu/~arnold/455.f96/disasters.html, а также theinquirer.net/inquirer/news/ 1047844/ (нашел только два...) - person Jaco Van Niekerk; 24.11.2011

Это распространенная ошибка с некоторыми компьютерными представлениями дробных чисел, см. этот вопрос или Google для точность с плавающей запятой.

person zoul    schedule 24.11.2011
comment
+1: Итак, настолько распространено, что удивительно, что люди не знают об этом. - person Peter Lawrey; 24.11.2011

Double не подходит для очень точных вычислений с плавающей запятой, если вам нужны точные результаты, вы должны использовать BigDecimal.

person Giovanni    schedule 24.11.2011
comment
Не нужно использовать BigDecimal в этом случае (который имеет ряд проблем). Достаточно правильно округлить на выходе. - person sleske; 24.11.2011
comment
@sleske: А какие проблемы с BigDecimal? Единственное, о чем я знаю, это производительность. - person bezmax; 24.11.2011
comment
@Max: в основном производительность (накладные расходы ЦП, использование памяти и дополнительная работа для сборщика мусора) и очень неуклюжий API (нет возможности использовать операторы). - person sleske; 24.11.2011
comment
@Max: существуют допустимые варианты использования BigDecimal. Я просто хотел указать, что в таком простом случае это на самом деле не нужно, и поэтому его следует избегать ИМХО. - person sleske; 24.11.2011