32,48 * 10 = 324,79999999999995 в вычислениях JavaScript - PullRequest
0 голосов
/ 10 августа 2011
var quantity = $(this).find('td:eq(2) input').val()*1;
var unitprice = $(this).find('td:eq(3) input').val()*1;
var totaltax = 0;
$(this).find('td:eq(4) input[name^=taxamount]').each(function(){
    totaltax = (totaltax*1)+($(this).val()*1);
});
var subtotal = (unitprice+totaltax);
alert(subtotal+' is unit subtotal, to mulitply by '+quantity);
var total = subtotal*quantity;
$(this).find('td:last').html('$'+total);

В этом случае, основываясь на моем DOM, все результаты являются целыми числами (особенно потому, что я проверяю, что я применяю модификатор * 1 к значениям, чтобы они были числами, а не строками).

В этом случае это значения, возвращаемые в первых 7 строках вышеуказанного кода (и проверяются с помощью команды alert) количество: 10 цена: 29 общий налог: 3,48 промежуточный итог = 32,48

Когда я умножаю итоговое * количество на общую переменную, итоговая сумма возвращается: всего: 324,79999999999995

Итак, в конце я получаю td: last, заполненное $ 324.79999999999995, а не $ 324.80, что было бы более правильным.

Странно, я знаю. Я пробовал всевозможные предупреждения в разных точках, чтобы убедиться в отсутствии ошибок и т. Д.

Ответы [ 7 ]

7 голосов
/ 10 августа 2011

Об этом спрашивали один миллиард раз.

Пожалуйста, прочитайте: Что каждый ученый должен знать об арифметике с плавающей точкой

4 голосов
/ 10 августа 2011

Вы сталкиваетесь со знакомой проблемой со значениями с плавающей запятой: некоторые значения не могут быть точно представлены в конечном двоичном числе с плавающей запятой.

Смотрите здесь:

Как справиться с точностью чисел с плавающей точкой в ​​JavaScript?

3 голосов
/ 10 августа 2011

Так работают числа с плавающей запятой.Здесь нет ничего странного.

Я бы порекомендовал вам округлить значение соответствующим образом для отображения.

1 голос
/ 10 августа 2011

Как уже упоминали другие, это способ работать. Предлагаемый обходной путь можно найти ниже:

var v = "324.32999999999995";

function roundFloat(n, d) {             
    var a= Math.pow(10, d);             
    var b= Math.round(n * a) / a;
    return b;         
}

$("body").append(roundFloat(v,3));

Где v будет заменено на желаемое значение.

Рабочий пример можно посмотреть по адресу: http://jsfiddle.net/QZXhc/

1 голос
/ 10 августа 2011

Компьютеры не могут хорошо обрабатывать десятичные числа в двоичном виде, поскольку в реальной математике буквально бесконечное число значений, например, от 0,01 до 0,02. Поэтому им нужно хранить аппроксимации, и когда вы выполняете арифметику с этими аппроксимациями, результаты могут немного отличаться от истинного результата.

Вы можете исправить это с помощью (Math.round(total*100)/100).toFixed(2);

1 голос
/ 10 августа 2011

Это радость арифметики с плавающей запятой - некоторые десятичные десятичные числа нельзя представить в двоичном виде.

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

0 голосов
/ 10 августа 2011

Вы можете попробовать округлить до 2 десятичных цифр как обходной путь

...