Почему 6.35.toFixed(1) == 6.3?
Методы Math.round
и toFixed
, согласно документации, округляют до ближайшего целого числа: 0..4
округляется в меньшую сторону, тогда как 5..9
в большую сторону.
Например:
alert( 1.35.toFixed(1) ); // 1.4
Но почему в примере ниже 6.35 округляется до 6.3?
alert( 6.35.toFixed(1) ); // 6.3
Как правильно округлить 6.35
?
Во внутреннем двоичном представлении 6.35 является бесконечной двоичной дробью. Хранится она с потерей точности…
Давайте посмотрим:
alert( 6.35.toFixed(20) ); // 6.34999999999999964473
Потеря точности может как увеличивать, так и уменьшать число. В данном случае число становится чуть меньше, поэтому оно округляется в меньшую сторону.
А для числа 1.35
?
alert( 1.35.toFixed(20) ); // 1.35000000000000008882
Тут потеря точности приводит к увеличению числа, поэтому округление произойдёт в большую сторону.
Каким образом можно исправить ошибку в округлении числа 6.35
?
Мы должны приблизить его к целому числу, перед округлением:
alert( (6.35 * 10).toFixed(20) ); // 63.50000000000000000000
Обратите внимание, что для числа 63.5
не происходит потери точности. Дело в том, что десятичная часть 0.5
на самом деле 1/2
. Дробные числа, делённые на степень 2
, точно представлены в двоичной системе, теперь мы можем округлить число:
alert( Math.round(6.35 * 10) / 10 ); // 6.35 -> 63.5 -> 64(rounded) -> 6.4