Jump to content

Проблемы с числами и их решение


Alexey

Recommended Posts

Сегодня затрону важную проблему, о которой не знают многие новички. Это не секретная информация и про это написано достаточно много, но новички так стремятся "в бой", что пропускают кучу важной информации. А потом удивляются, почему программа работает не так, как они хотят. Итак, сегодня рассмотрим две проблемы.
A): Подумайте что выведет это код? (не проверяйте через компьютер только)

console.log(6.6+3.3);
console.log(0.1+0.2);
console.log(0.3-0.1);

9.9; 0.3; 0.2?
Неправильно!
Ответы: 
9.899999999999999
0.30000000000000004
0.19999999999999998
Логично, что и (6.6+3.3) === 9.9 будет false
Почему так? Прочитайте про IEEE 754 и всё поймёте. Хотите знать как с этим бороться? Хорошо, дам 2 метода.
1): Не используйте операции с десятичными дробями. Храните исключительно целые числа и делайте их дробными прямо перед использованием.
2): Используйте toFixed. Значение 10 решает 99% проблем с дробями (у вас, конечное, будет только 10 знаков после запятой). Значение 5 решает 99.9999% всех проблем с дробями. Короче, чем ближе значение к 0, тем меньше проблем будет у вас с дробями (и тем меньше будет знаков после запятой).

console.log(+(6.6+3.3.toFixed(5)));

B):Подумайте, что выведет этот код(не проверяйте через компьютер только)
 

console.log(9999999999999999);
console.log(279999999999999448);

Ответы: 
10000000000000000
279999999999999460
Как с этим бороться? Очень просто! Не используйте слишком большие числа. Используйте числа  от −2147483648 до 2147483647 и проблем не будет 100% (можно и немного большие/меньшие числа использовать, но и этого диапозона всем хватает обычно).
Меня бесят всякие ошибки в вычислениях в JS (их явно больше, чем 2 описанные), что мне делать?

Если точные вычисления вам важны, то в JS храните все числа в String типе, а вычисления проводите с помощью плагинов (нормальными статически типизированными языками; Есть куча специальных языков для вычислений).
Вот так вот, за все удобства JS приходится платить точностью, но как только появляется точность, то тут же улетучивается всё удобство!

Edited by Alexey
  • Like 3
Link to comment
Share on other sites

  • 1 month later...
  • 1 month later...
  • 11 months later...
var sum1;
var sum2;
var firstcomp = 1000;
var secondcomp = 0.7;
var thirdcomp = -0.5;
var fourthcomp = -5;

var sum1 = firstcomp * (secondcomp + thirdcomp) / fourthcomp;
log.debug(sum1);
var sum2 = 1000 * (0.7 - 0.5) / -5;
log.debug(sum2);

 

В 23.03.2017 в 13:49, Alexey сказал:

Не используйте операции с десятичными дробями. Храните исключительно целые числа и делайте их дробными прямо перед использованием.

Вроде как все работает... и там и там ответы -39.(9)

Может я что то не так понял?

 

Link to comment
Share on other sites

  • 3 weeks later...
В 15.06.2018 в 17:43, MaxRaimer сказал:

var sum1;
var sum2;
var firstcomp = 1000;
var secondcomp = 0.7;
var thirdcomp = -0.5;
var fourthcomp = -5;

var sum1 = firstcomp * (secondcomp + thirdcomp) / fourthcomp;
log.debug(sum1);
var sum2 = 1000 * (0.7 - 0.5) / -5;
log.debug(sum2);

 

Вроде как все работает... и там и там ответы -39.(9)

Может я что то не так понял?

 

Ты неправильно понял. Первый способ заключается в том, чтобы перед операцией представить дробное число как целое. Например 0.2 мы можем представить как 2*10^(-1) и т.д. Конечно такое способ не рекомендуется, ибо слишком много операций будет выполнять компьютер. Вообще можно даже округление не использовать (и лучше не использовать), так как суперточные вычисления мало где сильно нужны (а где нужны там как раз и можно будет заморочиться). Главно никогда не использовать при сравнениях float (дробных) чисел == или === . Нужно <= или >= . Также не используй != !==

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...