Почему информация в моей функции printf() неверна в MQL4?
Мое форматирование печати дает мне случайные ответы, несмотря на то, что мое кодирование правильное. Я пытаюсь отобразить длину свечных баров предыдущих двух свечных баров до входа в сделку. Вот кодировка, которую я использовал.
PCL1
& PCL2
соответствующие поля ввода. Они делятся на _Point
дать целочисленное форматирование.
PCL2
= Предыдущая длина свечи, Shift 2
PCL1
= Предыдущая длина свечи, Shift 1
В этом примере я сосредоточился на подсвечнике Shift2
Short_Bull_2_Close = iClose( Symbol(), 0, 2 );
Short_Bull_2_Open = iOpen( Symbol(), 0, 2 );
CandleBody_2 = ( Short_Bull_2_Close - Short_Bull_2_Open );
// Gives the Candlebody length in pips.
А это мой printf()
кодирование:
printf( "PCL1 [%d] PCL2 [%d]", CandleBody_1 / Point,
CandleBody_2 / Point
); // ___________________________________________________________ SELL//
2 ответа
1) MQL4- язык со строгой типизацией (объявление предшествует любому использованию переменной)
+ MQL4 имеет историческую особенность числа "нормализация"
Предположение
(cit.)
"Они делятся на_Point
дать целое число " не имеет места.
После того, как любое число было объявлено double
в исходном коде как:
double upFractal = 0.0,
dnFractal = 0.0;
MQL4-компилятор обрабатывает эти числа навсегда в представлении чисел с плавающей запятой IEEE-754 и вызывает конкретную подверсию операций для любой арифметической операции, в которую входит это число. Причина проста, double
имеет другую обработку, чем (Новый - MQL4.56789
) float
чем больше int
и другие. Некоторые числа, представленные в IEEE-754, являются неточными по определению, некоторые могут оставаться точными (если они оказываются некоторой прямой степенью числа 2 и все еще находятся в "первичном" состоянии) (еще не были испорчены какой-либо арифметикой операция, которая привела бы к недопустимой точности в их бинарном представлении)).
Почему точность?
Почему нельзя избежать?
Для не девственных чисел двоичное представление может привести к бесконечно длинному описанию значения. Напротив, хранение любого значения в MQL4 ограничено { 1 | 4 | 8 }
-байт пространства памяти и, таким образом, бесконечное представление неизбежно обрезается на некотором расстоянии, внося принципиальную неточность, выраженную как:
DBL_EPSILON
~ 2.2204460492503131e-016
FLT_EPSILON
~ 1.192092896e-07
за пределами которого любые два числа, представленные в двоичном формате IEEE-754, выглядят для скомпилированного кода как "равные", даже если они не принципиально равны, просто из-за присущей im I-точности формата IEEE-754.
По действительно историческим причинам, double
введенные значения должны были быть всегда NormalizeDouble()
конвертируется, если кто-то хочет отправить их на серверную обработку MetaTrader и / или сравнить значения на справедливой основе.
2) MQL4 операции с {double | int }
- типизированные переменные
Если кто-то объявил переменную, чтобы быть double
, это остается double
навсегда.
Если кто-то объявил переменную, чтобы быть int
даже int/3
останется int
игнорируя дробные продукты операции деления (что иногда вызывает головные боли у не очень заботливых кодеров MQL4).
То же самое, примененное к первоначальному предположению выше, приводит к удивлению, что double/double -> double
даже в случаях деления можно было бы удовлетворительно считать (почти) целое число. Поэтому никогда не допускайте, чтобы преобразование типов происходило только по значениям операндов.
Для этого есть два вида синтаксической поддержки:
- явная функция преобразования
int( ... )
или жеdouble( ... )
- встроенная директива Typecast
( (int) CandleBody_1 / _Point )
Эпилог: (... необходимо прочитать для разработчиков пользовательских индикаторов, где производительность процессора убивает)
Как сказано выше, звоня
(int) NormalizeDouble(...)
это двойная чепуха (далеко за рамками парадигмы пояс + подтяжки), во-первых, как исторически встроенная функцияNormalizeDouble
все еще возвращаетсяdouble
таким образом, обеспечивая нулевую выгоду от затрат процессора на сокращение чисел, если он все еще даетdouble
, следующий как деление числа аdouble
ценность_Point
очень дорогой и неэффективный, по сравнению с тем,_Point
относится кint
ценностьDigits
по формуле1 / 10^Digits
- поэтому самым быстрым и чистым способом преобразования, не тратя процессорных циклов, которых можно избежать, является МУЛЬТИПЛИКАЦИЯ...
да,
с точки зрения быстрой и эффективной обработки на компьютереint( MAKE_aPriceDOMAIN_VALUE_an_INT_NUM_OF_POINTs * CandleBody_1 )
,
повторное использование константыint MAKE_aPriceDOMAIN_VALUE_an_INT_NUM_OF_POINTs = MathPow( 10, Digits );
Вы должны преобразовать в целое число, вы можете подумать, что вы получили действительное число, эквивалентное целому числу, но конвертер так не считает.
printf("%d", (int)NormalizeDouble(CandleBody_2/Point,0) );