Подтвердить что ты не робот

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

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

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

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

Ответ 1

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

0.5 is store as b0.1 
but 0.1 = 1/10 so it 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.1. 0.09375.

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

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

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

Ответ 2

Из руководства с плавающей точкой:

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

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

Когда код компилируется или интерпретируется, ваш "0.1" уже округляется до ближайшего числа в этом формате, что приводит к небольшой ошибке округления даже до того, как произойдет вычисление.

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

Ответ 3

Это не ограничение только на 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 может быть выражен только в виде бесконечной суммы степеней 2, которую язык отбрасывает в какой-то момент. Его это измельчение, которое вызывает эти незначительные ошибки.