В примере с суммой
0.1 + 0.2
решается
(0.1*10 + 0.2*10)/10 = 0.3
Как быть с 0.1 * 0.2 = 0.020000000000000004
Вариант с toFixed(n) не подойдет, т.к точность всегда нужна разная, в зависимости от перемножаемых значений
В примере с суммой
0.1 + 0.2
решается
(0.1*10 + 0.2*10)/10 = 0.3
Как быть с 0.1 * 0.2 = 0.020000000000000004
Вариант с toFixed(n) не подойдет, т.к точность всегда нужна разная, в зависимости от перемножаемых значений
Для чисел с плавающей запятой другая арифметика. Связано с тем, что если число однозначно не раскладывается на слагаемые, которые являются степенями двойки, то будет возникать "хвост" цифр после запятой. http://vestikinc.narod.ru/AB/ni_bin.htm
Результат вычисления для чисел с плавающей запятой нельзя сравнивать ни через == ни через ===, потому что этот хвостик может слегка отличаться. При сравнении используется округление до нужной степени точности.
не так: 0.1 + 0.2 ~= 0.3 (приблизительно равно) а вот так: abs((0.1 + 0.2) - 0.3) < 0.0001 , где 0.0001 - требуемая точность
Один из вариантов вычисления точности результата арифметических операций:
Пусть имеем два числа с плавающей запятой A и B. У числа А есть M цифр после запятой, а у B есть K цифр после запятой.
Нужно выполнить 4 операции: сложение, вычисление, деление, умножение.
При вычитании и сложении количество цифр после запятой равно максимуму из M и K:
Пример: число А = 0.111, количество цифр после запятой M = 3; B = 0.0001, количество цифр K = 4; количество цифр после запятой в результате = max(M;K) = max(3;4) = 4
Получается, что результат должен быть с 4 цифрами после запятой, а именно 0.111 + 0.0001 = 0.1111
При умножении А на B количество цифр после запятой равно сумме M и K.
Пример: число А = 0.111, количество цифр после запятой M = 3; B = 0.0001, количество цифр K = 4; количество цифр после запятой в результате = M + K = 3 + 4 = 7
0.111 * 0.0001 = 0.0000111 при округлении до 7 знака после запятой
При делении А на B количество цифр после запятой равно разности M и K. Если результат получился отрицательный, значит число получается целое, без дробной части
Пример: число А = 0.111, количество цифр после запятой M = 3; B = 0.0001, количество цифр K = 4; количество цифр после запятой в результате = M - K = 3 - 4 = -1
0.111 / 0.0001 = 1110 (округление до целых)
Пример: число А = 0.1111, количество цифр после запятой M = 4; B = 0.11, количество цифр K = 2; количество цифр после запятой в результате = M - K = 4 - 2 = 2
0.1111 / 0.11 = 1.01 (округление до 2х цифр после запятой)
С простой арифметикой разобрались ?
Для простоты всегда можно брать количество цифр после запятой в результате как как произведение M * K (корни, степени, логарифмы, тригонометрия), но из-за особенностей преобразования в двоичные числа всё равно может появиться "хвостик" незначащих цифр.
И эти положения про арифметику вообще никак не согласуются с тем, как результат будет сохранён в базе данных, передан по сети (в двоичном виде) и обработан получателем и много других аспектов. Это только про арифметику для реализации калькулятора.
При вычитании и сложении количество цифр после запятой равно максимуму из M и K:
ага, конечно - 0.00001 + 0.99999
пять цифр после запятой? С вычитанием все ещё проще. Там такие примеры сходу сочиняются.
При умножении А на B количество цифр после запятой равно сумме M и K.
Например 0.2*0.5 ... Ага, в компании с конечным нулем.
При делении А на B количество цифр после запятой равно разности M и K. Если результат получился отрицательный, значит число получается целое, без дробной части
0.1 / 0.03 = 3.333333... - ага, целое, без дробной.
- 0.00001 + 0.99999
0.99998 не вижу проблемы
Ага, в компании с конечным нулем
не вижу проблемы, незначащие нулевые разряды на точность не влияют
0.1 / 0.03 = 3.333333
Да, вы правы - http://take.ms/w1z7l . Пусть я ошибся. Возьмите для деления формулу: количество цифр после запятой = сумме M + K. А что даёт калькулятор в windows? Он считает с определённой точностью, в данном случае - 16 цифр после запятой. Исходников калькулятора у меня нет, проверить не могу.
– copist Jun 22 '14 at 19:030.00001 + 0.99999 минуса нет. Там сложение. А то, что Вы приняли за минус - это тире.
А что даёт калькулятор в windows?
У нас обсуждение javascript/google-калькулятора. Да и винда не у всех есть.
не вижу проблемы, незначащие нулевые разряды на точность не влияют
А автору вопроса как раз хочется "человеческий результат". Кстати, гугл калькулятор все нули в конце отбросит.
А BigNumber можно и написать свой, "правильный".
– KoVadim Jun 22 '14 at 19:34По какому критерию определяет Google калькулятор, что
0.1 * 0.2 = 0.02
А 0.4 * 0.4 = 0.16, а не 0.16000000000000003
по тому же критерию, по которому 0.16000000000000003 +1 = 1.16 в гуглокалькуляторе (округляем по какой-то знак, не знаю точно по какой)
– zb' Jun 22 '14 at 22:40parseFloat((1/10+2/10).toPrecision(16)) //0.3
(для справки в гугле 1000000000000001-1000000000000000=0)
– zb' Jun 22 '14 at 23:50Если Вам нужно "нормальное поведение" (я специально взял в кавычки), то нужно написать (или взять чужую готовую) библиотеку для длинной арифметики. Такую библиотеку написать на самом деле не очень сложно и для разминки мозгов самое оно. Само число можно представить в виде строки (да, строки) или массива цифр + порядок. Сложение/вычитание делается легко, с умножением чуточку сложнее (придется вспомнить, что такое умножение в столбик). Потом деление и корень квадратный. Все остальное будет просто.
Для javascript есть BigNumber.
(0.1*10*0.2*10)/100– Yura Ivanov Jun 21 '14 at 17:59