Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Функция написана на С
На mql5 действительно выдает 0.
А на C# выдает 1.
Может mql кривой?
//---Сама функция.
С другими аргументами на C# что? Странная какая-функция.
А вот и функция которая считает количество знаков после запятой у любого числа:
Нюанс который не нравиться чисто эстетически - 3 раза взятие модуля, как бы это уменьшить.
А вот и функция которая считает количество знаков после запятой у любого числа:
Нюанс который не нравиться чисто эстетически - 3 раза взятие модуля, как бы это уменьшить.
Перед началом цикла сделать num=MathAbs(num), внутри цикла будет достаточно одного MathAbs
В каких случаях эта функция будет неправильно работать?
Всё догнал. Думал не догоню. ))) Всем спасибо за помощь. Тему можно в архив.
Могли бы и подсказать. Что такие *****то? ) Ответ то банальный. Ппц.
...
Могли бы и подсказать. Что такие *****то? )
...
А вот и функция которая считает количество знаков после запятой у любого числа:
{
uchar i=0;
for(i=0;i<=DBL_DIG;i++) if (MathAbs(MathAbs(NormalizeDouble(num,i))-MathAbs(num))<=DBL_EPSILON) break;
return(i);
}
Нюанс который не нравиться чисто эстетически - 3 раза взятие модуля, как бы это уменьшить.
Я не знаю, разобрались ли вы самостоятельно в том, что ваша функция - не для любых чисел типа double.
Кроме того, вы сами наверное знаете, что сталкиваясь с ложными утверждениями, не редко нет желания что-либо пояснять/приводить аргументы.
Недавно я решила всё-таки немного обновить опубликованный вариант своей функции (обновлённый привожу в конце поста).
Попутно, позднее, решила всё-таки написать здесь своими, простыми словами о следующем (некоторое, как минимум с первого по третий пункт, прозвучит банально, но привожу ниже всё для отображения своей точки зрения: в целях взаимоувязки, бо́льшей смысловой полноты, но без углубления в какие-то детали, усложняющие восприятие):
1. Числа типа double имеют особенности в целом. Т.е., не с привязкой именно к языкам программирования MQL5 и MQL4.
При работе с этими числами нам, естественно, может быть требоваться учитывать их особенности.
2. При трейдинге может требоваться различная точность по десятичным знакам (в т.ч., на одних графиках - пять знаков, на других графиках - три знака, и т.д., и т.д., и т.д. в разном и в одном и том же по разному).
3. Языки программирования MQL5 и MQL4 позволяют работать с числами типа double, имеющими различное значимое количество десятичных знаков. И разными способами.
В этих языках есть:
- обширная библиотека различных готовых функций (их можно посмотреть, например, в папках MetaEditor (сама я ещё не познакомилась подробно со всеми имеющимися там функциями, их очень и очень много): Include => Math и других);
- различные функции, с которыми можно познакомиться через F1 в Справке к MetaEditor.
Кроме того, эти языки позволяют конструировать какие-то свои варианты, в том числе, "изобретать велосипеды". Программирование - творческий процесс.4. Одна из функций в Справке - это NormalizeDouble().
Помню, на форуме упоминалось со стороны разработчиков, что она была создана для нормализации цены при выставлении отложенных ордеров и стопов.
Но её возможности (удобные "побочные" эффекты), позволили применять её не только для этого.
5. Функция NormalizeDouble() имеет ограничение по digits: от 0 до 8 знаков.
Убедиться в этом можно по разному.
Вот тест из самых простейших (я привожу здесь и далее упрощённые данные, чтобы при пояснении не вдаваться/не отвлекаться в различные детали):
//---
input int i_digits=15;
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
TEST_PRINT_TWO(NormalizeDouble(1.123456789,i_digits),DoubleToString(1.123456789,i_digits));
}
//+------------------------------------------------------------------+
Результат:
Т.е., при нормализации в 15 знаков, функция NormalizeDouble выводит число, имеющее девять десятичных знаков, с количеством в восемь и округляя при этом: 1.123456789 => 1.12345679
Дополнено: При этом само нормализуемое число не округляется. Округлённым будет значение, присваиваемое этой функцией какой-либо переменной. Если кратко примером, что подразумеваю, то как-то так примерно:
double c=NormalizeDouble(a,4);
//---
TEST_PRINT_TWO(DoubleToString(a),DoubleToString(c));
TEST_PRINT_ONE(DoubleToString(NormalizeDouble(a,4)));
TEST_PRINT_ONE(DoubleToString(a));
Результат:
22, OnStart, DoubleToString(NormalizeDouble(a,4)) = 1.12860000
23, OnStart, DoubleToString(a) = 1.12859000
Т.е., значение a - осталось прежним, побывав в NormalizeDouble(), нормализованное значение у c
Если для работы требуются значения больше восьми знаков, а эффект нужен подобный NormalizeDouble(), то, естественно, можно применять не её, а другие способы. Не её можно применять и для чисел с до восьми десятичных.
Кроме того, учитывая то, что максимальная точность на графиках сейчас, насколько знаю, это пять десятичных знаков, то значимая точность в 8 знаков - это, имхо, более чем достаточно для работы с ордерами, объектами и другой "повседневкой".
Попутно задам следующий вопрос:
Если кто-либо считает, что, например, для графических объектов и иной повседневки при трейдинге этого недостаточно и нужна значимая точность значений больше восьми знаков после запятой, то приведите, пожалуйста, реальные практические (не теоретические) примеры.
В своей формуле, Alexey, вы применяете NormalizeDouble().
Где ставите:
- digits, равный DBL_DIG. Согласно Справке, DBL_DIG = 15. Оно у вас стоит в цикле for со знаком <=, т.е., вырастает до 16.
- DBL_EPSILON - согласно Справке, это наименьшее число для которого выполняется условие 1.0+DBL_EPSILON != 1.0 (2.2204460492503131e-016)
К чему это может приводить:Для чисел, наподобие 0.1020, ваша функция, как и моя, будет показывать количество десятичных знаков, равное трём.
Но для чисел, например, 1.098665432 (здесь по факту девять десятичных знаков), ваша функция показывает наличие 16-ти десятичных знаков. Что ведёт к тому, что, например, можно считать числа, ненормализованными до интересующего, в то время как они нормализованы до интересующего.
Мои же варианты функции для определения количества десятичных знаков, в которых применяю Normalizable(), имели и имеют в коде явные предупреждения об ограничении в восемь знаков.
Вы говорили, что готовы поверить конкретному коду, а не просто словам.
Вот код:
", ",(#v2)," = ",(v2),", ",(#v3)," = ",(v3))
//+------------------------------------------------------------------+
void OnStart()
{
//---
double array[]=
{
0.0, //actual 0 => function = 0
1.0, //actual 0 => function = 0
1.09, //actual 2 => function = 2
1.09801, //actual 5 => function = 5
1.095, //actual 3 => function = 3
1.09826, //actual 5 => function = 5
1.098365, //actual 6 => function = 6
1.0985658, //actual 7 => function = 7
1.09816543, //actual 8 => function = 8
1.098665432, //actual 9 => function = 16
1.0989654321, //actual 10 => function = 16
5.895, //actual 3 => function = 3
0.1020, //actual 3 => function = 3
9.10208, //actual 5 => function = 5
1.0560, //actual 3 => function = 3
3.050608, //actual 6 => function = 6
1.090905, //actual 6 => function = 6
8.000000001, //actual 9 => function = 16
86.68100000000001 //actual 14 => function = 16
};
for(int i=ArraySize(array)-1;i>=0;i--)
{TEST_PRINT_THREE(i,DoubleToString(array[i],15),fnDigits(array[i]));}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
uchar fnDigits(double num)
{
uchar i=0;
for(i=0;i<=DBL_DIG;i++) if (MathAbs(MathAbs(NormalizeDouble(num,i))-MathAbs(num))<=DBL_EPSILON) break;
return(i);
}
//+------------------------------------------------------------------+
Как видите, я не вносила никаких изменений в вашу функцию.
Результат (он же, выше в коде комментариями):
39, OnStart, i = 17, DoubleToString(array[i],15) = 8.000000001000000, fnDigits(array[i]) = 16
39, OnStart, i = 16, DoubleToString(array[i],15) = 1.090905000000000, fnDigits(array[i]) = 6
39, OnStart, i = 15, DoubleToString(array[i],15) = 3.050608000000000, fnDigits(array[i]) = 6
39, OnStart, i = 14, DoubleToString(array[i],15) = 1.056000000000000, fnDigits(array[i]) = 3
39, OnStart, i = 13, DoubleToString(array[i],15) = 9.102080000000001, fnDigits(array[i]) = 5
39, OnStart, i = 12, DoubleToString(array[i],15) = 0.102000000000000, fnDigits(array[i]) = 3
39, OnStart, i = 11, DoubleToString(array[i],15) = 5.895000000000000, fnDigits(array[i]) = 3
39, OnStart, i = 10, DoubleToString(array[i],15) = 1.098965432100000, fnDigits(array[i]) = 16
39, OnStart, i = 9, DoubleToString(array[i],15) = 1.098665432000000, fnDigits(array[i]) = 16
39, OnStart, i = 8, DoubleToString(array[i],15) = 1.098165430000000, fnDigits(array[i]) = 8
39, OnStart, i = 7, DoubleToString(array[i],15) = 1.098565800000000, fnDigits(array[i]) = 7
39, OnStart, i = 6, DoubleToString(array[i],15) = 1.098365000000000, fnDigits(array[i]) = 6
39, OnStart, i = 5, DoubleToString(array[i],15) = 1.098260000000000, fnDigits(array[i]) = 5
39, OnStart, i = 4, DoubleToString(array[i],15) = 1.095000000000000, fnDigits(array[i]) = 3
39, OnStart, i = 3, DoubleToString(array[i],15) = 1.098010000000000, fnDigits(array[i]) = 5
39, OnStart, i = 2, DoubleToString(array[i],15) = 1.090000000000000, fnDigits(array[i]) = 2
39, OnStart, i = 1, DoubleToString(array[i],15) = 1.000000000000000, fnDigits(array[i]) = 0
39, OnStart, i = 0, DoubleToString(array[i],15) = 0.000000000000000, fnDigits(array[i]) = 0
Более детально (по значениям и оборотам внутри своей функции) вы можете провести тестирование самостоятельно.
Можете потом посмотреть работу моей:
//|NumberOfDigitsGet - number of digits after decimal point |
//+------------------------------------------------------------------+
//|2015, Dina Paches (Updated: 2016.12.12) |
//|dipaches.blogspot.com |
//|https://login.mql5.com/ru/users/dipach |
//+------------------------------------------------------------------+
int NumberOfDigitsGet(const double value,
const int digits=8)//<= F1: NormalizeDouble() to 8
{
int dig=(digits<1 || digits>8) ? 8 : digits;
//---
if(NormalizeDouble(value,dig)==0){return(0);}
//---
double val=value;
//---
if(NormalizeDouble(val,dig)<0){val=MathAbs(val);}
//---
double int_value=MathFloor(val);
//---
val=NormalizeDouble(val-int_value,dig);
//---
if(NormalizeDouble(val,dig)==0){return(0);}
//---
int variable =(int)MathPow(10,dig);
variable =(int)(NormalizeDouble(val*variable,0));
//---
string text =IntegerToString(variable);
variable =StringLen(text);
//---
for(int i=variable-1;i>=0;i--)
{
if(StringFind(text,"0",i)==i){dig--;}
else {return(dig);}
}
//---
return(dig);
}
//+------------------------------------------------------------------+