Я добавляю общие вычисления на стороне клиента на страницу моего заказа, так что дисконт объема покажет, когда пользователь делает выбор.Будет ли это надежным способом обработки ошибок округления при умножении чисел с плавающей запятой на Javascript?
Я нахожу, что некоторые вычисления отключены на один цент здесь или там. Это не будет очень большой сделкой, за исключением того факта, что общая сумма не соответствует окончательной общей расчетной серверной стороне (в PHP).
Я знаю, что ошибки округления являются ожидаемым результатом при работе с числами с плавающей запятой. Например, 149,95 * 0,15 = 22,492499999999996 и 149,95 * 0,30 = 44,98499999999999. Первые раунды по желанию, последний - нет.
Я искал эту тему и нашел множество дискуссий, но ничего не удовлетворительно решает проблему.
Мой текущий расчет заключается в следующем:
discount = Math.round(price * factor * 100)/100;
Общее предложение работать в центах, а не фракциям долларов. Тем не менее, это потребовало бы, чтобы я преобразовал свои стартовые номера, объединил их, умножил их на результат и затем преобразовал обратно.
По существу:
discount = Math.round(Math.round(price * 100) * Math.round(factor * 100)/100)/100;
Я думал о добавлении 0,0001 к числу до округления. Например:
discount = Math.round(price * factor * 100 + 0.0001)/100;
Это работает для сценариев, которые я пробовал, но мне интересно о моей логике. Будет ли добавление 0,0001 всегда достаточным и не слишком большим, чтобы добиться желаемого результата округления?
Примечание: Для моих целей здесь меня интересует только один расчет за цену (так что не усугубляйте ошибки) и никогда не будет отображаться более двух знаков после запятой.
EDIT: Например, я хочу округлить результат 149.95 * 0.30 до двух знаков после запятой и получить 44.99. Однако, я получаю 44.98, потому что фактический результат 44.98499999999999 не 44.985. Ошибка не вводится / 100
. Это происходит до этого.
Тест:
alert(149.95 * 0.30); // yields 44.98499999999999
Таким образом:
alert(Math.round(149.95 * 0.30 * 100)/100); // yields 44.98
44,98, как ожидается, с учетом фактического результата умножения, но не желателен, так как это не то, что пользователь будет ожидать (и отличается от результат PHP).
Решение: Я собираюсь преобразовать все в целые числа, чтобы выполнить мои вычисления. Как отмечается в принятом ответе, я могу несколько упростить мой первоначальный расчет. Моя идея добавить 0.0001 - это просто грязный хак. Лучше всего использовать правильный инструмент для работы.
Просто не используйте поплавки на деньги вообще? – delnan
Вы не указали проблему. Вы заявляете, что 44.984999 ... не округляется по желанию, но вы не указываете, к чему это округляется, к чему вы хотите объединить его или как вы показываете значение. Одна из возможностей заключается в том, что '/ 100' в вашей операции округления вводит ошибку округления, которая производит значение, которое вы не хотите, последующее преобразование этого значения для отображения показывает значение, которое вы не хотите. Там могут быть способы исправить это, но вы должны предоставить дополнительную информацию. –
@delnan Что вы используете вместо этого? Я хватаю цены из HTML, которые отображаются пользователю в долларах и центах. Я могу * конвертировать * их в центы, что я и сделаю, но я должен начать с float. – toxalot