Строковая в double переводится без проблем. Обратно - получаем другой результат.
Т.е. взял строку "8.905", преобразовал ее в double и сразу в string, получив 8.904999999999999. Но первая строка OnStart показывает, что (double)"8.905" == 8.905. Т.е. должно было выводиться 8.905.
Конечно, очевидная ситуация с нулем на конце не должна работать:
Если выполняется условие (double)"8.9050" == 8.9050, то должно выполняться и условие (string)(double)"8.9050" == "8.9050".
Немного исследовав вопрос, пришел к такой ситуации
Прошу объяснить, почему все равно считается, что преобразование double -> string происходит корректно. Последний пример так совсем выносит мозг.
Комментарий по последнему примеру
Вещественные числа могут считаться одинаковыми, если над ними производили одни и те же преобразования. Даже вроде бы одинаковые преобразования - num*0.5 и num/2.0 приводят к разным результатам. То же самое можно сказать про зеркальные операции. num*=num2, num/=num2. Полученный num не будет равен исходному num. Добро пожаловать в мир вещественных чисел.
В данном примере в процессе нормализации с вещественным числом были произведены 3 операции - num*=1000, num+=0.5, num/=1000
fxsaber: В СД говорят, что все правильно в этом случае
А почему смущает?
Подавляющее большинство десятичных вещественных чисел непредставимы в виде двоичной дроби без остатка. Накладываем на это формат хранения числе double и получаем такие некрасивости.
Вещественные числа могут считаться одинаковыми, если над ними производили одни и те же преобразования. Даже вроде бы одинаковые преобразования - num*0.5 и num/2.0 приводят к разным результатам. То же самое можно сказать про зеркальные операции. num*=num2, num/=num2. Полученный num не будет равен исходному num. Добро пожаловать в мир вещественных чисел.
В данном примере в процессе нормализации с вещественным числом были произведены 3 операции - num*=1000, num+=0.5, num/=1000
Можете проверить по шагам в отладчике
Очень конструктивное объяснение, Спасибо!
Но вот такой контрпример выносит несколько мозг
voidOnStart()
{
constdouble Num = 8.274;
constdouble Norm = NormalizeDouble(Num, 3);
Print(Num); // 8.273999999999999Print(Norm); // 8.274000000000001Print((double)DoubleToString(Num, 3) == Num); // true - без нормализации все замечательноPrint((double)DoubleToString(Norm, 3) == Norm); // false - а после нормализации полный облом!
}
Да, его отсутствие в софте, который работает с ценами, с самого начала существования МТ, мягко говоря, смущает.
PS. Теперь, при наличии ООП языка, MQ наверно считают, что желающие могут себе класс написать. Только его потом в простую структуру не положишь - нужно будет сериализовать/десериализовать во что-то простое типа ulong.
Я в самом деле очень благодарен Вам, что столь подробно отвечаете. Нормализация используется для формирования торговых запросов.
В этом примере окажется, что отправляются разные цены в двух этих OrderSend.
При этом всегда считалось, что умножение целого на Point не требует доп. нормализации (так задавали SL и TP, например).
Так какая из двух строк вызовет ошибку?
Прикольно
#include <MT4Orders.mqh>
voidOnStart()
{
constdouble Num = 8.274;
constdouble Norm = NormalizeDouble(Num, 3);
Print(Num); // 8.273999999999999Print(Norm); // 8.274000000000001Print((double)DoubleToString(Num, 3) == Num); // true - без нормализации все замечательноPrint((double)DoubleToString(Norm, 3) == Norm); // false - а после нормализации полный облом!OrderSend("USDSEK", OP_BUYLIMIT, 1, Num, 0, 0, 0);
OrderSend("USDSEK", OP_BUYLIMIT, 1, Norm, 0, 0, 0);
}
Результат
script Test (EURUSD,M1) loaded successfully
'6185283': buy limit 1.00 USDSEK at 8.27400
'6185283': accepted buy limit 1.00 USDSEK at 8.27400
'6185283': order #158260308 buy limit 1.00 / 1.00 USDSEK at market done in 98.718 ms
'6185283': buy limit 1.00 USDSEK at 8.27400
'6185283': accepted buy limit 1.00 USDSEK at 8.27400
'6185283': order #158260309 buy limit 1.00 / 1.00 USDSEK at market done in 120.328 ms
script Test (EURUSD,M1) removed
Оба запроса с разными ценами, но выполнились без проблем по одной и той же цене. Как так?
Утро вечера мудреннее... :)
Обычно так и есть :)Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Ошибки, баги, вопросы
fxsaber, 2017.07.18 09:51
Почти детский вопрос: почему так?По какой-то причине был уверен, что после нормализации DoubleToString лишен смысла. Ан нет, как показывает скрипт. Почему так?
Похоже, что неправильно работает приведение double -> string.
Пример довольно сложен для понимания, поэтому привел другой
Речь вот о чем
Строковая в double переводится без проблем. Обратно - получаем другой результат.
Т.е. взял строку "8.905", преобразовал ее в double и сразу в string, получив 8.904999999999999. Но первая строка OnStart показывает, что (double)"8.905" == 8.905. Т.е. должно было выводиться 8.905.
Конечно, очевидная ситуация с нулем на конце не должна работать:
Немного исследовав вопрос, пришел к такой ситуации
Прошу объяснить, почему все равно считается, что преобразование double -> string происходит корректно. Последний пример так совсем выносит мозг.
Прошу объяснить, почему все равно считается, что преобразование double -> string происходит корректно. Последний пример так совсем выносит мозг.
Комментарий по последнему примеру
Вещественные числа могут считаться одинаковыми, если над ними производили одни и те же преобразования. Даже вроде бы одинаковые преобразования - num*0.5 и num/2.0 приводят к разным результатам. То же самое можно сказать про зеркальные операции. num*=num2, num/=num2. Полученный num не будет равен исходному num. Добро пожаловать в мир вещественных чисел.
В данном примере в процессе нормализации с вещественным числом были произведены 3 операции - num*=1000, num+=0.5, num/=1000
Можете проверить по шагам в отладчике
В СД говорят, что все правильно в этом случае
А почему смущает?
Подавляющее большинство десятичных вещественных чисел непредставимы в виде двоичной дроби без остатка. Накладываем на это формат хранения числе double и получаем такие некрасивости.
Вообще тип decimal не помешал бы, удобная штука.
Комментарий по последнему примеру
Вещественные числа могут считаться одинаковыми, если над ними производили одни и те же преобразования. Даже вроде бы одинаковые преобразования - num*0.5 и num/2.0 приводят к разным результатам. То же самое можно сказать про зеркальные операции. num*=num2, num/=num2. Полученный num не будет равен исходному num. Добро пожаловать в мир вещественных чисел.
В данном примере в процессе нормализации с вещественным числом были произведены 3 операции - num*=1000, num+=0.5, num/=1000
Можете проверить по шагам в отладчике
Очень конструктивное объяснение, Спасибо!
Но вот такой контрпример выносит несколько мозг
Разве должна так работать нормализация?
А почему смущает?
После объяснения Славы уже не смущает, но далее возник пример, который заставляет усомниться в правильности работы теперь уже самой NormalizeDouble.
Вообще тип decimal не помешал бы, удобная штука.
Да, его отсутствие в софте, который работает с ценами, с самого начала существования МТ, мягко говоря, смущает.
PS. Теперь, при наличии ООП языка, MQ наверно считают, что желающие могут себе класс написать. Только его потом в простую структуру не положишь - нужно будет сериализовать/десериализовать во что-то простое типа ulong.Я в самом деле очень благодарен Вам, что столь подробно отвечаете. Нормализация используется для формирования торговых запросов.
В этом примере окажется, что отправляются разные цены в двух этих OrderSend.
При этом всегда считалось, что умножение целого на Point не требует доп. нормализации (так задавали SL и TP, например).
Так какая из двух строк вызовет ошибку?
Да, его отсутствие в софте, который работает с ценами, с самого начала существования МТ, мягко говоря, смущает.
Я в самом деле очень благодарен Вам, что столь подробно отвечаете. Нормализация используется для формирования торговых запросов.
В этом примере окажется, что отправляются разные цены в двух этих OrderSend.
При этом всегда считалось, что умножение целого на Point не требует доп. нормализации (так задавали SL и TP, например).
Так какая из двух строк вызовет ошибку?
Прикольно
Результат
Оба запроса с разными ценами, но выполнились без проблем по одной и той же цене. Как так?