Pergunta para os mestres da MQL4. Novamente sobre Double Compare. - página 5

 

Conclusão surpreendente! O que o faz pensar que com qualquer dígito, se você nem sequer "entende" o que é um dígito?

 
Integer:

Conclusão surpreendente! O que o faz pensar que com qualquer dígito, se você nem sequer "entende" o que é um dígito?

Você está começando a pegar nas palavras? Obviamente, isto vai ser um assassinato de personalidade. :)
Devo dizer imediatamente que prefiro não participar de tais explicações, porque se você não tem nada a dizer sobre os méritos, por que falar?
 
VBAG:
Eu gostaria de agradecer a todos os profissionais por sua visão!

Irtron, eu escolhi sua variante, eu gostei muito. Corrigi-o um pouco para casos gerais e verifiquei-o:

int Comparação Preço (duplo a, duplo b, duplo dígito)
{
a -= b;
b = dígito;
se (a > b)
retorno (1);
se (a < -b)
retorno (-1);
retorno (0);
}
Obrigado.
Esqueci de esclarecer que quero passar qualquer valor pré-definido para o dígito:
double digit14=0.00000000000001;
dígito duplo12=0,000000000001;
dígito duplo8=0,00000001;
dígito duplo4=0,0001;
dígito duplo2=0,01;
que determinará a precisão necessária.
Para esta funcionalidade, ele funciona muito rapidamente.
Irtron, mais uma vez obrigado.

 
Irtron:
Inteiro:

Conclusão surpreendente! O que o faz pensar que com qualquer dígito, se você nem mesmo "entende" qual dígito é?

Começando a pegar nas palavras? Obviamente, a partir de agora vai se tornar pessoal. :)
Devo dizer imediatamente que prefiro não participar de tais explicações, porque se você não tem nada a dizer sobre os méritos, por que falar?


Por que escolher, acabei de ler o que você escreveu. Sua compreensão é obviamente dificultada por "sua gritante... (você dá o nome à palavra)".

VBAG, por que reinventar a roda quando existe uma função NormalizeDouble() que compara dois números mais rápido do que CompararPreço()?

 
Integer:

VBAG, por que reinventar a roda quando há uma função NormalizeDouble() que compara dois números mais rápido do que CompararPreço()?

A função compara dois números duplos e dá a resposta <, > ou = a 14 casas decimais (NormalizeDouble() é limitado a 8 dígitos)
Se você puder sugerir uma bicicleta semelhante ou soluções alternativas melhores, eu ficaria feliz em usá-las.
Respeitosamente,
Vladimir
 
VBAG:
Inteiro:

VBAG, por que reinventar a roda quando há uma função NormalizeDouble() que compara dois números mais rápido do que CompararPreço()?

A função compara dois números duplos e dá a resposta <, > ou = a 14 casas decimais (NormalizeDouble() é limitado a 8 dígitos)
Se você puder sugerir uma roda semelhante ou alternativas melhores, eu ficaria feliz em usá-las.
Respeitosamente,
Vladimir
Aqui está um teste para meu interesse:
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 $CheckCompareDouplo USDJPY,M5: CD: 20485, xNormalizar: 51265

Conclusão:
A função CD compara dois números duplos, dá a resposta <, > ou = com 14 casas decimais e funciona 2 vezes mais rápido do que simplesmente executar NormalizeDouble()(mesmo sem lógica para compará-los).
 
Sim, duas chamadas para NormalizeDouble() levam mais tempo que um CD, e uma chamada é mais rápida. Precisão de 14 dígitos é um toque agradável :-)
 
Eu também tenho tentado comparar números reais recentemente!

Muitas pessoas escrevem que para comparar devem usar a função NormalizeDouble(). (isto é o que os desenvolvedores também recomendam).
Portanto, eu gostaria de definir primeiro: "o que é NormalizeDouble()?", ou seja, como funciona, qual é o seu algoritmo.

MQL4 Reference - Conversões de dados - NormalizeDouble

Arredondamento de um número de ponto flutuante para uma precisão especificada.
...

Não sei como o arredondamento é organizado na MQL4 (pergunte aos desenvolvedores), mas conheço um método padrão Arredondamento de números de ponto flutuante para precisão especificada:
Aqui, uma função:

double MyNormalizeDouble(double value, int digits)
{
    int factor = MathRound( MathPow(10, digits) ); // factor - это множитель,
                                                      с помощью которого мы из VALUE сделаем целое число
    double result = MathRound(factor * value) / factor;
    
    return(result);
}
A partir desta função você pode ver que primeiro passamos de um número real para um número inteiro, e depois voltamos a um número real novamente.
Para comparação, basta ir apenas até um número inteiro.

Portanto, acredito que a maneira mais rápida e mais confiável de comparar números reais é convertê-los em números inteiros.
Esta é a aparência da comparação:

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
}

Tudo isso pode ser formatado em uma função e utilizado. É uma dor de escrever, parece estar claro como se faz uma função!
Acho que este caminho é mais rápido do que chamar de NormalizeDouble().

Por segurança, você também pode fazer com que a função MathRound() retorne um número inteiro, já que por padrão ela retorna o dobro.
A maneira mais fácil de fazer desta maneira

int MyMathRound(double value)
{
    int result = MathRound(value);
    return(result);
}
Então apenas inteiros serão comparados, e eles comparam bem!


Acho que desta forma é a mais correta, não acha?
 
gravity001:

Portanto, acho que a maneira mais rápida e confiável é converter os números reais em números inteiros.
A comparação ficaria assim:

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
}

Acho que essa é a maneira correta de fazer isso, não acha?

Acho que não. Julgue por si mesmo:
Toda a beleza do código Irtron está em sua compacidade (absolutamente nada a mais - até mesmo variáveis são salvas!).
E você sugere que devemos acrescentar mais duas operações para cada
(а - b)
operação, pelo menos.
(MathRound( (а - b) * factor ) 
Isso é uma vantagem de velocidade!
 
VBAG:
Acho que não. Julgue por si mesmo

Sim, um pouco mais lento:
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 ));
}
ComparePreço: 32032, intCompare: 35296