При сложении в JavaScript возникает много знаков после запятой?

Делаю в JavaScript-консоли Opera Dragonfly:


>>> 31.01+1

32.010000000000005

>>> 31.02+1

32.019999999999996

>>> 31.03+1

32.03


Вариации с parseFloat/parseInt ни к чему не привели, откуда берется 0.000000000000005 в первом случае и куда девается 0.000000000000004 во втором?
  • Вопрос задан
  • 15924 просмотра
Пригласить эксперта
Ответы на вопрос 8
xaker1
@xaker1
Скорей всего особенность чисел с плавающей запятой.
Дело в том, что при кодировании некоторых чисел двоичный код получается бесконечным. Например 0.1 в двоичной системе — 0.0(0011). В памяти компьютера это будет 1.1001100110011001100110011001100110011001100110011010b * 2^(-4), а при переводе в десятичную — 0.10000000000000000555111512.

ИМХО это одна из проблем динамической типизации.
Ответ написан
taliban
@taliban
php программист
(31.01+1).toFixed(2)
Ответ написан
@Ano
Это ерунда :) Фокусы с IEEE double:

>>> 9007199254740992
9007199254740992

>>> 9007199254740993
9007199254740992

>>> 9007199254740994
9007199254740994

>>> 9007199254740995
9007199254740996


Читайте en.wikipedia.org/wiki/Double_precision_floating-point_format

Если нужна точность, вычисляйте с фиксированной точкой ((31,01·100 + 1·100)÷100). Не нравится представление, используйте toFixed.
Ответ написан
Комментировать
hf35
@hf35
Math.round используйте
Ответ написан
Вообще-то вот неточные вычисления. Там есть почему и как бороться, хотя тут вообщем-то уже ответили. Но это как прув, так как сайт вполне авторитетный.

Кстати, я начал изучения javacript с этого учебника. Сразу в голове, конечно, не уложится, но во-время написания кода всплывет и спасет от таких детских ошибок.
Ответ написан
Комментировать
OlegTar
@OlegTar
программист .NET, Javascript, Perl
var t = 2.32356121212;

function fixed(N, n) {
  return Math.round(t * Math.pow(10, n))/Math.pow(10, n);
}

fixed(t, 4);


Вывод:
2.3236
Ответ написан
keksmen
@keksmen
Just a programmer
Если не боитесь "страшных" потерь производительности от преобразования в строки есть вот такой хак:
function (num) {
    var a=num%1;
    var b=Math.pow(10,num.toString().split('.')[1].length);
    return Math.round(a*b)/b;
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы