[Решено] Странный результат сложения чисел

 

Здравствуйте все!

Обнаружил при тестировании советника в MT5. Откуда берётся такая дробная часть?

Подскажите, что это за фокус и как его победить? Есть какие-то хитрые хитрости при сложении чисел double?

double w=3.28+81.37;

Alert(w);
Alert((string)w);
Alert(NormalizeDouble(w,2));
Alert(MathRound(w*100)/100);

выдаёт

Alert: 84.65000000000001

Alert: 84.65000000000001

Alert: 84.65000000000001

Alert: 84.65000000000001

Вот ещё (с попытками повлиять на них):

Alert(102.54-37.3);
Alert((string)(111.25-12.01));
double x=(string)NormalizeDouble(89.77-6.98,2);Alert(x);
Alert(-41.25-30.4);
Alert(-69.16-12.08);
Alert(-95.17+28.93);

Результат:

Alert: 65.24000000000001
Alert: 99.23999999999999
Alert: 82.79000000000001
Alert: -71.65000000000001
Alert: -81.23999999999999
Alert: -66.24000000000001

И такое странное не только в алертах, но и при записи в файл.

В общем, то ли лыжи не в полном порядке, то ли я не совсем здоров :)

На чём обнаружил:

2017.06.21 17:37:50.412 Terminal        MetaTrader 5 x64 build 1495 started (MetaQuotes Software Corp.)
2017.06.21 17:37:50.414 Terminal        Microsoft Windows 7 (x64 based PC) on Wine, IE 09.00, Intel Pentium 4  2.40GHz, RAM: 4537 / 7688 Mb, HDD: 85894 / 199494 Mb, GMT+02:00

Впрочем и под Win такой же результат:

2017.06.21 16:45:11.789 Terminal        Alpari Limited MT5 x64 build 1596 started (Alpari Limited)
2017.06.21 16:45:11.789 Terminal        Windows 7 Ultimate (x64 based PC), IE 08.00, Intel Core i5-3210M  @ 2.50GHz, RAM: 1432 / 2047 Mb, HDD: 3914 / 30616 Mb, GMT+02:00


 
kofesutra:

Здравствуйте все!

Обнаружил при тестировании советника в MT5. Откуда берётся такая дробная часть?

Подскажите, что это за фокус и как его победить? Есть какие-то хитрые хитрости при сложении чисел double?

...

Это нормально.

https://www.mql5.com/ru/docs/basis/types/double

Из справочника по ссылке:

"Необходимо помнить, что вещественные числа хранятся в памяти компьютера с некоторой ограниченной точностью в двоичной системе счисления, в то время как общепринятой в использовании является десятичная система счисления. Поэтому многие числа, которые точно записываются в десятичной системе, в двоичной системе можно записать только в виде бесконечной дроби.

Например, числа 0.3 и 0.7 представлены в компьютере бесконечными дробями, в то время как число 0.25 хранится точно, так как представляет из себя степень двойки."

Документация по MQL5: Основы языка / Типы данных / Вещественные типы (double, float)
Документация по MQL5: Основы языка / Типы данных / Вещественные типы (double, float)
  • www.mql5.com
Основы языка / Типы данных / Вещественные типы (double, float) - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Sergey Basov:

Это нормально.

Сергей, спасибо за ответ.

А что делать-то с этим? Как жЫть?

Хочется, чтобы результат вычислений тоже имел дробную часть не дальше сотых.

 


Вот, положим, такая конструкция срабатывает:

Alert((float)(3.28*100+81.37*100)/100);

Получается как надо

Alert: 84.65

Лыжи поехали чуть лучше, но всё равно - это сомнительный костыль.

 
kofesutra:

Вот, положим, такая конструкция срабатывает:

Получается как надо

Лыжи поехали чуть лучше, но всё равно - это сомнительный костыль.

нормализуйте до нужного значения функцией NormalizeDouble

 
Konstantin:

нормализуйте до нужного значения функцией NormalizeDouble

В первом посте уже пробовал :(
 
DoubleToString(w,2);
 
kofesutra:

Сергей, спасибо за ответ.

А что делать-то с этим? Как жЫть?

Хочется, чтобы результат вычислений тоже имел дробную часть не дальше сотых.

На практике я встречался только с двумя проблемами:

1) Сравнение между собой двух double на равенство.

2) Неудобство визуального восприятия таких странных дробей при выводе, например через Print() или Alert().

Решение как обычно оказалось в справочнике.

Так что жЫть можно ))

 
Taras Slobodyanik:

Тарас, дорогой Вы мой человек, спасибо! Всё работает :)

Alert(DoubleToString(3.28+81.37,2));
Alert(DoubleToString(102.54-37.3,2));
Alert(DoubleToString(111.25-12.01,2));
Alert(DoubleToString(89.77-6.98,2));
Alert(DoubleToString(-41.25-30.4,2));
Alert(DoubleToString(-69.16-12.08,2));
Alert(DoubleToString(-95.17+28.93,2));

Alert: 84.65
Alert: 65.24
Alert: 99.24
Alert: 82.79
Alert: -71.65
Alert: -81.24
Alert: -66.24
 
Sergey Basov:

2) Неудобство визуального восприятия таких странных дробей при выводе, например через Print() или Alert().



Да ладно, что в алертах, но и при записи в файл :( что совсем не нужно.

 

Такие мелочи не имеют глобального международного значения.