Вы не можете влоб сравнивать вещественные типы double, Вы может только проверять разницу. То есть, запись
StopLoss/Point-MathFloor(StopLoss/Point)!=0
не может гарантировать коррректной работы алгоритма. Правильно будет так:
MathAbs(StopLoss/Point-MathFloor(StopLoss/Point))< delta
В данном случае, delta =1 (единице).
и что получится? если разность будет равна 0, то будет также некорректно алгоритм работать
если такая строка будет:
if (MathAbs(StopLoss/Point-MathFloor(StopLoss/Point))>0 && MathAbs(StopLoss/Point-MathFloor(StopLoss/Point))<1)
{
MessageBox("Некорректно задан уровень StopLoss."+"\n"+
"Количество знаков после запятой не должно превышать "+DoubleToStr(Digits,0)+"\n"+
"Программа закончит свою работу!","Проверка исходных данных!");
return(0);
}
то всё равно на определённых числовых значениях алгоритм не работает
дело не в сравнении вещественных типов double.
дело в том, что функция MathFloor(1.3457/0.0001) возвращает значение не 13457, а 13456
ещё раз второй вариант скрипта прикрепляю, в котором происходит просто округление
вводите цифру 1.2457, делите на 0.0001, округляете и получается корректное значение 12457
вводите цифру 1.3457, делите на 0.0001, округляете и получаете значение 1.3456
вот в чём непонятки...
баг это или что по вашему?
Числа типа double могут на самом деле быть не тем, чем они кажутся. Только имея дело с типом int Вы можете быть в чем-то уверены. Вот пример вычисления вашего выраежния, запустите этот скрипт:
//+------------------------------------------------------------------+ //| DemostrateDouble.mq4 | //| Copyright © 2008, MetaQuotes Software Corp. | //| http://forum.mql4.com/cn/17189 | //+------------------------------------------------------------------+ #property copyright "Copyright © 2008, MetaQuotes Software Corp." #property link "http://forum.mql4.com/cn/17189" #include <stdlib.mqh> //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { //---- double div = 1.3457/0.0001; int floor = MathFloor(div); Print("floor = ", floor," div = ",DoubleToStr(div, 8)); Print(" div с 16 знаками после запятой " , DoubleToStrMorePrecision(div,16)); //---- return(0); } //+------------------------------------------------------------------+
и увидите такой результат:
ну я уже догадался сам, что получается при делении отличное от должного значение.
вопрос в том, какой из вариантов расчёта неверен:
1) расчёт 1.3457/0.0001 с точностью 30 знаков после запятой в таблице Excel;
2) расчёт средствами языка MQL?
и если данную ошибку языка исправить нельзя, то может подскажете обходной алгоритм для определения корректности дробного числа?
например, я таким способом определял необходимый сайз сделки, то есть при заданном риске определял необходимый лот и проверял его на соответствие торговым условиям:
size=MarketInfo(Symbol(),MODE_LOTSIZE);
size=0.01*Risk*AccountBalance()/(MathAbs(openprice-stoploss)*size);
size=MathFloor(size/step_lot)*step_lot;
тут получается если число целое, то гуд, если дробное, то дробь отбрасывается и реальный лот оказывается меньше расчётного.
как теперь поступать, если такой способ неправильно расчитывается?
Нужно изменить свое отношение. Если Вы не понимаете чем обусловлено такое поведение при делении типа double, то можно воспользоваться поиском.
Вот например, ветка Неясные приоритеты
if (StopLoss/Point-MathFloor(StopLoss/Point)!=0)
на строку:
if (NormalizeDouble(StopLoss/Point,1)!=MathFloor(NormalizeDouble(StopLoss/Point,1)))
{
MessageBox("Некорректно задан уровень StopLoss."+"\n"+
"Количество знаков после запятой не должно превышать "+DoubleToStr(Digits,0)+"\n"+
"Программа закончит свою работу!","Проверка исходных данных!");
return(0);
}
посмотрел ссылку, которую Вы разместили здесь. речь там идёт о приведении типов, что 7/10=0, а 7.0/10.0=0.7
это я уже знал, но никак не могу понять (хоть намекните что забить в поиск...) почему типы double - 1.2457/0.0001=12457.0, а 1.3457/0.0001=13456.9999999999999, почему одинаковые числа считаются так разно, всё равно что по аналогии 7.0/10.0=0.7, а 8.0/10.0=0.799999...
Вы считаете, это не есть ошибочной расчёт?!
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
есть функция:
есть отрывок кода:
if (StopLoss/Point-MathFloor(StopLoss/Point)!=0)
{
MessageBox("Некорректно задан уровень StopLoss."+"\n"+
"Количество знаков после запятой не должно превышать "+DoubleToStr(Digits,0)+"\n"+
"Программа проверит ошибки исходных данных и закончит свою работу!","Проверка исходных данных!");
}
суть в следующем - если уровень стоплосс содержит большее количество цифр после запятой, то это некорректный уровень стоплосс.
ошибка в чём? если уровень стоплосс содержит необходимое количество цифр после запятой, то код всё равно возвращает ошибку.
Почему?
потому что к примеру 1.3457/0.0001=13457 после обработки функцией double MathFloor(double x) становится равно 13456. хотя должно возвращать "...числовое значение, представляющее наибольшее целое число, которое меньше или РАВНО х"
прилагаю небольшой скрипт. его нужно повесить на валютную пару с 4-мя или 5-ю знаками после запятой. интересное тут в том, что значение 1.2457 определяется корректно, а значение 1.3457 - уже нет
странно, что для одних значений считается всё корректно, для других - нет