Почему добавление двух десятичных знаков в Javascript дает неправильный результат? [дубликат]

Возможный дубликат:
Не нарушена ли математика JavaScript?

Почему JS испортил эту простую математику?

 console.log (.1 + .2) // 0.3000000000000004 console.log (.3 + .6) // 0.8999999999999999 

Первый пример больше правильного результата, а второй меньше. ??? !! Как вы это исправите? Вы должны всегда преобразовывать десятичные числа в целые числа перед выполнением операций? Должен ли я беспокоиться только о добавлении (* и / в моих тестах, похоже, нет такой же проблемы)?

Я искал ответы во многих местах. Некоторые учебные пособия (например, формы корзины покупок) делают вид, что проблемы не существует, и просто добавляют значения вместе. Гуру предоставляют сложные подпрограммы для различных математических функций или упоминают, что JS «делает плохую работу» мимоходом, но я пока не вижу объяснения.

56
задан Madara Uchiha 14 May 2019 в 15:04
поделиться

5 ответов

Это не проблема JS, а более общая компьютерная проблема. Плавающее число не может правильно хранить все десятичные числа, потому что они хранят данные в двоичном формате. Например:

0.5 is store as b0.1 
but 0.1 = 1/10 so it's 1/16 + (1/10-1/16) = 1/16 + 0.0375
0.0375 = 1/32 + (0.0375-1/32) = 1/32 + 00625 ... etc

so in binary 0.1 is 0.00011... 

, но это бесконечно. Но в какой-то момент компьютер должен остановиться. Итак, если в нашем примере мы остановимся на 0,00011, мы получим 0,09375 вместо 0,1.

Во всяком случае, дело в том, что это зависит не от языка, а от компьютера. От языка зависит то, как вы показываете числа. Обычно язык округляет числа до приемлемого представления. По-видимому, JS этого не делает.

Итак, что вам нужно сделать (число в памяти достаточно точное), это просто каким-то образом сказать JS, чтобы он округлял «красиво» числа при преобразовании их в текст.

Вы можете попробовать функцию sprintf , которая дает вам точный контроль над отображением числа.

33
ответ дан 26 November 2019 в 17:30
поделиться

Из The Floating-Point Guide :

Почему нет моих чисел, например 0,1 + 0,2 в сумме получается хороший раунд 0,3, и вместо этого я получаю странный результат вроде 0,30000000000000004?

Поскольку внутри компьютеров используется формат (двоичная с плавающей запятой), который не может точно представить число вроде 0,1, 0,2 или вообще 0,3.

Когда код компилируется или интерпретируется, ваше «0,1» уже округляется до ближайшего числа в этом формат, что приводит к небольшому ошибка округления еще до расчет бывает.

На сайте есть подробные объяснения, а также информация о том, как решить проблему (и как решить, является ли это проблемой вообще в вашем случае).

13
ответ дан 26 November 2019 в 17:30
поделиться

Это ограничение касается не только JavaScript, оно применяется ко всем вычислениям с плавающей запятой. Проблема в том, что 0,1, 0,2 и 0,3 не могут быть точно представлены в виде javascript (или C, или Java и т. Д.) С плавающей точкой. Таким образом, результат, который вы видите, вызван этой неточностью.

В частности, точно представимы только некоторые суммы степеней двойки. 0,5 = = 0,1b = 2 ^ (- 1), 0,25 = 0,01b = (2 ^ -2), 0,75 = 0,11b = (2 ^ -1 + 2 ^ -2) все в порядке. Но 1/10 = 0,000110001100011..b может быть выражено только как бесконечная сумма степеней двойки, которую язык в какой-то момент отбрасывает. Именно это измельчение вызывает эти небольшие ошибки.

8
ответ дан 26 November 2019 в 17:30
поделиться

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

4
ответ дан 26 November 2019 в 17:30
поделиться

Это связано с тем, как компьютеры обрабатывают плавающие числа. Вы можете прочитать об этом подробнее здесь: http://docs.sun.com/source/806-3568/ncg_goldberg.html

1
ответ дан 26 November 2019 в 17:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: