@LeonidPokrovskiy

JavaScript неправильно вычитает числа 8.18 — 1.99. В чем дело?

Есть страница, на которой юзеры выбирают услуги. Каждая услуга стоит денег. Внизу страницы есть блок, в котором показывается стоимость всех выбранных услуг.

Первая услуга стоит 1.99$
Вторая услуга стоит 6.19$

1. Юзер выбирает сначала 2 услуги. total_price = 1.99 + 6.19 = 8.18

2. Юзер отменяет первую услугу total_price = 8.18 - 1.99 = 6.1899999999999995

Когда я увидел это число в поле "Итоговая стоимость" я сразу полез в код искать что не так. Искал минут 30 - все в порядке!

В итоге решил ввести в консоли 8.18 - 1.99 и вывелось 6.1899999999999995.

Почему?

Я даже на калькуляторе посчитал - 8.18 - 1.99 = 6,19

В чем дело?
  • Вопрос задан
  • 354 просмотра
Решения вопроса 4
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
1. Никогда не вычитайте из суммы: всегда пересчитываете сумму из набора услуг (TOTAL=k1x1+k2x2+...+kNxN)!
2. Точность вычислений: floatNum.toPrecision()
3. Точность допуска (расстояние, погрешность) - проверяйте так:
if (Math.Abs(x1 - x2) < delta) { ... }.
Ответ написан
@yvetrov
Дело в том, что JavaScript может ошибаться, если числа дробные, так называемые "числа с плавающей точкой". Подробнее вы можете разобраться в статье.

Как решение, вы можете использовать библиотеку Dinero или использовать метод .toFixed(n). Библиотека создана для расчета неизменяемых денежных величин.
Ответ написан
KickeRocK
@KickeRocK
FrontFinish
Тут написано про точность
The maximum number of decimals is 17, but floating point arithmetic is not always 100% accurate

To solve the problem above, it helps to multiply and divide:

var x = (0.2 * 10 + 0.1 * 10) / 10;       // x will be 0.3
Ответ написан
Комментировать
@Karpion
Если Вы работаете со штучными товарами - то держите цены в копейках, они целочисленные.

Если товар весовой - то перед выводом ответа всегда округляйте до копеек. Примерно так:
округлённая_цена = к_ближайшему_целому ( посчитанная_цена * 100 ) / 100

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

Я в своё время в 1С столкнулся с такой проблемой - когда минеральную воду из Сарова продавали по двадцать рублей за упаковку из шести бутылок, а в документах надо было указывать цену за одну бутылку.
(Это так, воспоминания о моей жизни, перегруженные ненужными Вам подробностями.)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
lamer350
@lamer350
กำลังสูงสุด
Простите конечно, тут просто не знаю даже если возможность шутить... Но вы примерно 6 999 9999 999й человек который это заметил. Вы хоть одну книжку по JS видели?
Ответ написан
SagePtr
@SagePtr
Еда - это святое
Это особенность архитектуры процессора, а не языка программирования, все числа (в том числе и с плавающей точкой) он хранит в двоичном виде. А десятичные дроби далеко не все можно представить в виде конечных двоичных дробей. Самый яркий пример: 0.1 + 0.2.
Ответ написан
Ваш ответ на вопрос

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

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