Вопрос к мастерам MQL4. Опять про Double Compare. - страница 5

 

Удивительный вывод! С чего вы взяли что при любом digit, если даже "вообще не поняли" что такое digit?

 
Integer:

Удивительный вывод! С чего вы взяли что при любом digit, если даже "вообще не поняли" что такое digit?

Начинаете придираться к словам? Дальше, очевидно, пойдет выяснение личностей. :)
Скажу сразу, я в подобных выяснениях предпочитаю не участвовать, потому как, если по существу сказать нечего, зачем вообще говорить?
 
VBAG:
Хочу выразить огромную благодарность всем профи за ликбез!

Irtron, выбрал для себя Ваш вариант, ну очень он мне понравился. Чутка подправил для общих случаев, проверил - работает как часы:

int ComparePrice(double a, double b, double digit)
{
a -= b;
b = digit;
if (a > b)
return (1);
if (a < -b)
return (-1);
return (0);
}
Спасибо.
Забыл пояснить, что в digit хочу в лоб передавать любое заранее объявленное значение:
double digit14=0.00000000000001;
double digit12=0.000000000001;
double digit8=0.00000001;
double digit4=0.0001;
double digit2=0.01;
которое и будет определять требуемую точность.
Для такой функциональности работает очень быстро.
Irtron, еще раз благодарю.

 
Irtron:
Integer:

Удивительный вывод! С чего вы взяли что при любом digit, если даже "вообще не поняли" что такое digit?

Начинаете придираться к словам? Дальше, очевидно, пойдет выяснение личностей. :)
Скажу сразу, я в подобных выяснениях предпочитаю не участвовать, потому как, если по существу сказать нечего, зачем вообще говорить?


Почему же придираться, я только прочитал то, что вы написали. Вашему понимаю очевидно мешает "ваша откровенная... (слово поставьте сами)"

VBAG, зачем изобретать велосипед, если существует функция NormalizeDouble(), при использовании которой сравнение двух чисел выполняется быстрее, чем при помощи функции ComparePrice()?

 
Integer:

VBAG, зачем изобретать велосипед, если существует функция NormalizeDouble(), при использовании которой сравнение двух чисел выполняется быстрее, чем при помощи функции ComparePrice()?

Функция сравнивает два числа double и дает ответ <, > или = с точностью 14 знаков после запятой.(NormalizeDouble() ограничен 8 знаками)
Если Вы предложите подобный велосипед или лучшие альтернативные решения, с удовольствием буду их использовать.
С уважением,
Владимир
 
VBAG:
Integer:

VBAG, зачем изобретать велосипед, если существует функция NormalizeDouble(), при использовании которой сравнение двух чисел выполняется быстрее, чем при помощи функции ComparePrice()?

Функция сравнивает два числа double и дает ответ <, > или = с точностью 14 знаков после запятой.(NormalizeDouble() ограничен 8 знаками)
Если Вы предложите подобный велосипед или лучшие альтернативные решения, с удовольствием буду их использовать.
С уважением,
Владимир
Вот для интереса провел тест:
int start()
  {
//----
    double a = 1.23450001, b = 1.23449999;
 
    int start1 = GetTickCount(), c1;
    for ( c1 = 0; c1 < 100000000; c1 ++ ) CD( a, b,0.00000001);
    int end1 = GetTickCount();
    
 
    int start2 = GetTickCount(), c2;
    for ( c2 = 0; c2 < 100000000; c2 ++ )   xNormalize(a,b,8);
    int end2 = GetTickCount();
 
    Print( "CD: ", (end1-start1), ", xNormalize: ", (end2-start2) );
 
    return(0);
   }
 
//+ CompareDouble ---------------------------------------------------+ CompareDouble
int CD(double a, double b, double digit)
{
    a -= b;
    b = digit;
    if (a > b)
        return (1);
    if (a < -b)
        return (-1);
    return (0);
}
 
// Две операции NormalizeDouble----
bool xNormalize(double a, double b,int digit)
  {
   double d1 = NormalizeDouble(a,digit);
   double d2 = NormalizeDouble(b,digit);
   
//   bool bCompare=d2-d1 > 0.0;
   bool bCompare= 0;
   return(bCompare);
2007.09.12 07:15:09 $CheckCompareDouble USDJPY,M5: CD: 20485, xNormalize: 51265

Вывод:
Функция СD сравнивает два числа double , дает ответ <, > или = с точностью 14 знаков после запятой и работает быстрее в 2 раза простого выполнения NormalizeDouble()(даже без логики их сравнения).
 
Да, два вызова NormalizeDouble() рабтают дольше чем CD, а один вызов - быстрее. Точность 14 знаков - подкупает:-)
 
Недавно тоже пытался сравнивать вещественные числа!

Многие пишут, что для сравнения надо использовать встроенныю функцию NormalizeDouble(). (так и разработчики рекомендуют)
Поэтому хотелось бы сначала определить: "что такое NormalizeDouble()?", т.е. как она работает, каков её алгоритм работы.

Справочник MQL4 - Преобразования данных - NormalizeDouble

Округление числа с плавающей запятой до указанной точности.
...

Как в MQL4 организованно округления я не знаю (это надо спросить у разработчиков), но я знаю стандартный метод Округление числа с плавающей запятой до указанной точности:
Вот, функция:

double MyNormalizeDouble(double value, int digits)
{
    int factor = MathRound( MathPow(10, digits) ); // factor - это множитель,
                                                      с помощью которого мы из VALUE сделаем целое число
    double result = MathRound(factor * value) / factor;
    
    return(result);
}
Из это функции видно, что мы сначала переходим от вещественного числа к целому,  а потом опять к вещественному.
Для сравнения достаточно перейти только к целому числу.

Поэтому, я думаю самое быстрое и надежное это перевести вещественные числа в целые
Сравнение будет выглядеть так:

double a;
double b;
int factor = MathRound( MathPow(10, digits) ); // digits - это точность с которой будем сравнивать
                                                           Если сравниваем цены, то это предопределенная переменная Digits
...

if (MathRound( (а - b) * factor )  !=  0)
{
    ... // a != b
}

if (MathRound( (а - b) * factor )  ==  0)
{
    ... // a == b
}

if (MathRound( (а - b) * factor )  >  0)
{
    ... // a > b
}

if (MathRound( (а - b) * factor )  <  0)
{
    ... // a < b
}

Все это можно оформить в функцию и пользоваться. Ломает писать, вроде понятно как сделать функцию!
Думаю, такой способ быстрее, чем вызывать NormalizeDouble().

Для надежности можно еще сделать чтобы функция MathRound() возращала целочисленное число, а  то по умолчанию она возращает double.
Самый простой способ сделать так

int MyMathRound(double value)
{
    int result = MathRound(value);
    return(result);
}
 Тогда будут сравниваться только целые числа, а они сравниваются хорошо!


Думаю, этот способ вообще самый правильный, а вы?
 
gravity001:

Поэтому, я думаю самое быстрое и надежное это перевести вещественные числа в целые
Сравнение будет выглядеть так:

double a;
double b;
int factor = MathRound( MathPow(10, digits) ); // digits - это точность с которой будем сравнивать
                                                           Если сравниваем цены, то это предопределенная переменная Digits
...

if (MathRound( (а - b) * factor )  !=  0)
{
    ... // a != b
}

if (MathRound( (а - b) * factor )  ==  0)
{
    ... // a == b
}

if (MathRound( (а - b) * factor )  >  0)
{
    ... // a > b
}

if (MathRound( (а - b) * factor )  <  0)
{
    ... // a < b
}

Думаю, этот способ вообще самый правильный, а вы?

Думаю, что нет. Судите сами:
Вся прелесть, кода который предложил Irtron, заключается в его компактности( абсолютно ничего лишнего-даже на переменных экономия!)
А Вы предлагаете как минимум на каждую операцию
(а - b)
повесить еще две операции
(MathRound( (а - b) * factor ) 
Вот и пройгрыш в скорости!
 
VBAG:
Думаю, что нет. Судите сами

Да, чуть медленнее:
int start()
{
    double a, b;
    int start1, start2, end, c;
    
    a = 1.23450001;
    b = 1.23449999;
    
    start1 = GetTickCount();
    
    for (c = 100000000; c > 0; c--)
        ComparePrice(a, b,0.0001);
    
    start2 = GetTickCount();
    
    for (c = 100000000; c > 0; c--)
        intCompare(a, b,10000);
    
    end = GetTickCount();
 
    Print("ComparePrice: ", start2 - start1, ", intCompare: ", end - start2);
 
    return(0);
}
 
int ComparePrice(double a, double b, double point)
{
    a -= b;
    b = point / 2.;
    if (a > b)
        return (1);
    if (a < -b)
        return (-1);
    return (0);
}
 
int intCompare(double a, double b, int factor)
{
    return(MathRound( (a-b) * factor ));
}
ComparePrice: 32032, intCompare: 35296
Причина обращения: