Realmente, não se podem comparar as duplas. É apenas uma regra difícil.
Naturalmente, é possível e por vezes até necessário comparar directamente entre si as duplas.
Por exemplo, o OnTick é por vezes chamado um trilião de vezes durante a Optimização. A fim de compreender se deve ou não executar um limite pendente, o testador incorporado compara o preço actual do símbolo correspondente e o preço limite. Fá-lo para cada encomenda pendente antes de cada chamada OnTick. Ou seja, estes controlos são feitos dezenas e centenas de milhares de milhões de vezes.
E é feito de cada vez através da normalização. Bem, isto é um desperdício horrível de recursos informáticos. Uma vez que os preços das encomendas pendentes e o símbolo são preliminarmente normalizados. Portanto, podem e devem ser comparados directamente uns com os outros.
O MQL-tester de MQL-personalizado tem um desempenho facilmente superior ao do testador nativo integrado em desempenho.
Naturalmente, é possível e por vezes até necessário comparar directamente entre si as duplas.
Por exemplo, OnTick é por vezes chamado um trilião de vezes durante a Optimize. O testador incorporado, a fim de compreender se deve ou não executar um limite pendente, compara o preço actual do símbolo correspondente e o preço limite. Fá-lo para cada encomenda pendente antes de cada chamada OnTick. Ou seja, estes controlos são feitos dezenas e centenas de milhares de milhões de vezes.
E é feito de cada vez através da normalização. Bem, isto é um desperdício horrível de recursos informáticos. Uma vez que os preços das encomendas pendentes e o símbolo são preliminarmente normalizados. Portanto, podem e devem ser comparados directamente uns com os outros.
O MQL-tester de MQL-personalizado tem um desempenho facilmente superior ao do testador nativo integrado em desempenho.
NormalizeDouble() é uma função muito cara. Por conseguinte, é melhor esquecer isso.
Aqui está um guião que demonstra a diferença entre NormalizeDouble() e normalize com int:
#define SIZE 1000000int Ceil (double x) {return (x-(int)x>0)?(int)x+1:(int)x;}
int Round(double x) {return (x>0)?(int)(x+0.5):(int)(x-0.5);}
int Floor(double x) {return (x>0)?(int)x:((int)x-x>0)?(int)x-1:(int)x;}
//+------------------------------------------------------------------+//| Script program start function |//+------------------------------------------------------------------+voidOnStart()
{
double a[SIZE];
double s1=0,s2=0, s3=0;
for (int i=0;i<SIZE;i++) a[i]=(rand()-16384)/M_PI;
ulong t1=GetMicrosecondCount();
for (int i=0;i<SIZE;i++) s1+=a[i];
t1=GetMicrosecondCount()-t1;
ulong t2=GetMicrosecondCount();
for (int i=0;i<SIZE;i++) s2+=NormalizeDouble(a[i],5);
t2=GetMicrosecondCount()-t2;
ulong t3=GetMicrosecondCount();
for (int i=0;i<SIZE;i++) s3+=Round(a[i]*100000);
s3/=100000;
t3=GetMicrosecondCount()-t3;
Print("простая сумма - " + string(t1)+ " микросекунд, сумма = "+ DoubleToString(s1,18));
Print("сумма с NormalizeDouble - " + string(t2)+ " микросекунд, сумма = "+ DoubleToString(s2,18));
Print("сумма, нормализированная через int - " + string(t3)+ " микросекунд, сумма = "+ DoubleToString(s3,18));
}
NormalizeDouble() é uma função muito cara. É por isso que é melhor esquecê-lo.
Aqui está um guião que demonstra a diferença entre NormalizeDouble() e normalize com int:
resultado:
SZZ a normalização por int é ainda mais precisa (pode ver-se isto pelo número de noves após o último dígito da normalização - realçado a azul).
e se a soma não é via dupla, mas via longa, então o resultado é ainda mais impressionante, visto que a soma via int (multiplicação e arredondamento seguido pela divisão da soma final) calcula mais rapidamente do que a soma normal da dupla.
#define SIZE 1000000int Ceil (double x) {return (x-(int)x>0)?(int)x+1:(int)x;}
int Round(double x) {return (x>0)?(int)(x+0.5):(int)(x-0.5);}
int Floor(double x) {return (x>0)?(int)x:((int)x-x>0)?(int)x-1:(int)x;}
//+------------------------------------------------------------------+//| Script program start function |//+------------------------------------------------------------------+voidOnStart()
{
double a[SIZE];
double s1=0,s2=0, s3=0;
long s=0;
for (int i=0;i<SIZE;i++) a[i]=(rand()-16384)/M_PI;
ulong t1=GetMicrosecondCount();
for (int i=0;i<SIZE;i++) s1+=a[i];
t1=GetMicrosecondCount()-t1;
ulong t2=GetMicrosecondCount();
for (int i=0;i<SIZE;i++) s2+=NormalizeDouble(a[i],5);
t2=GetMicrosecondCount()-t2;
ulong t3=GetMicrosecondCount();
for (int i=0;i<SIZE;i++) s+=Round(a[i]*100000);
s3=s/100000.0;
t3=GetMicrosecondCount()-t3;
Print("простая сумма - " + string(t1)+ " микросекунд, сумма = "+ DoubleToString(s1,18));
Print("сумма с NormalizeDouble - " + string(t2)+ " микросекунд, сумма = "+ DoubleToString(s2,18));
Print("сумма, нормализированная через int - " + string(t3)+ " микросекунд, сумма = "+ DoubleToString(s3,18));
}
E se a soma não é via dupla, mas via longa, então o resultado é ainda mais impressionante, porque a soma via int (multiplicação e arredondamento, seguido pela divisão da soma total) é mais rápida do que uma soma dupla normal.
Nikolai Semko: Além disso, a normalização através de int também se revela mais precisa (pode vê-la pelo número de noves após o último dígito de normalização - realçado a azul).
O teste está incorrecto. Porque se divide por 100000.0 apenas uma vez no final? Deve ser realizado em cada iteração e depois resumido. É uma comparação justa. Mas isto não é normalização de todo - acabou de optimizar o seu algoritmo de teste. Naturalmente, será mais rápido e mais preciso (porque o erro acumulado é reduzido).
Porque pode introduzir preços não-normalizados ao Testador e este trata-os de forma idêntica.
Afinal, mesmo que os preços não estejam normalizados, a verificação é facilmente feita sem qualquer normalização.
Por normalização quis dizer neste caso, um único algoritmo padrão, após a sua aplicação, é possível comparar directamente duplicações deste padrão.
Assim, o testador não compara directamente as duplas. Fá-lo através de NormalizeDouble, ticksize ou qualquer outra coisa. Mas certamente não através da comparação directa de duplas. E não é de todo racional.
Naturalmente, é possível e por vezes mesmo necessário comparar directamente entre si as duplas.
Por exemplo, o OnTick é por vezes chamado um trilião de vezes durante a Optimize. O testador incorporado, a fim de compreender se deve ou não executar uma chamada de limite pendente, compara o preço actual do símbolo correspondente e o preço da chamada de limite. Fá-lo para cada encomenda pendente antes de cada chamada OnTick. Ou seja, estes controlos são feitos dezenas e centenas de milhares de milhões de vezes.
E é feito de cada vez através da normalização. Bem, isto é um desperdício horrível de recursos informáticos. Uma vez que os preços das encomendas pendentes e o símbolo são preliminarmente normalizados. Portanto, podem e devem ser comparados directamente uns com os outros.
O MQL-tester de MQL-personalizado não bate o testador nativo incorporado em desempenho.
Por isso, decidi verificar a versão sem sentido do desempenho. E o resultado foi surpreendente. A comparação até do dobro pré-normalizado é ainda mais lenta em média do que quando se compara o dobro através do epsilon ou conversão para int
#define SIZE 1000000int Ceil (double x) {return (x-(int)x>0)?(int)x+1:(int)x;}
int Round(double x) {return (x>0)?(int)(x+0.5):(int)(x-0.5);}
int Floor(double x) {return (x>0)?(int)x:((int)x-x>0)?(int)x-1:(int)x;}
bool is_equal(double d1, double d2, double e=0.000000001) {returnfabs(d1-d2)<e;}
voidOnStart()
{
double a[SIZE], a_norm[SIZE];
int s1=0,s2=0, s3=0;
for (int i=0;i<SIZE;i++) {
a[i]=(rand()-16384)/1641.1452;
a_norm[i]=NormalizeDouble(a[i],2);
}
double test = 1.11;
ulong t1=GetMicrosecondCount();
for (int i=0;i<SIZE;i++) if (a_norm[i]==test) s1++;
t1=GetMicrosecondCount()-t1;
ulong t2=GetMicrosecondCount();
for (int i=0;i<SIZE;i++) if (is_equal(a[i],test,0.005)) s2++;
t2=GetMicrosecondCount()-t2;
ulong t3=GetMicrosecondCount();
int test_int = test*100;
for (int i=0;i<SIZE;i++) if (Round(a[i]*100)==test_int) s3++;
t3=GetMicrosecondCount()-t3;
Print("простое сравнение предварительно нормализированых double - " + string(t1)+ " микросекунд, всего совпадений = "+ string(s1));
Print("сравнение double через эпсилон - " + string(t2)+ " микросекунд, всего совпадений = "+ string(s2));
Print("сравнение double через преобразование в int - " + string(t3)+ " микросекунд, всего совпадений = "+ string(s3));
}
O resultado:
2020.08.1014:31:39.620 TestCompareDouble (USDCAD,H4) простое сравнение предварительно нормализированых double - 900 микросекунд, всего совпадений = 4862020.08.1014:31:39.620 TestCompareDouble (USDCAD,H4) сравнение double через эпсилон - 723 микросекунд, всего совпадений = 4862020.08.1014:31:39.620 TestCompareDouble (USDCAD,H4) сравнение double через преобразование в int - 805 микросекунд, всего совпадений = 4862020.08.1014:31:42.607 TestCompareDouble (USDCAD,H4) простое сравнение предварительно нормализированых double - 1533 микросекунд, всего совпадений = 4882020.08.1014:31:42.607 TestCompareDouble (USDCAD,H4) сравнение double через эпсилон - 758 микросекунд, всего совпадений = 4882020.08.1014:31:42.607 TestCompareDouble (USDCAD,H4) сравнение double через преобразование в int - 790 микросекунд, всего совпадений = 4882020.08.1014:31:44.638 TestCompareDouble (USDCAD,H4) простое сравнение предварительно нормализированых double - 986 микросекунд, всего совпадений = 4722020.08.1014:31:44.638 TestCompareDouble (USDCAD,H4) сравнение double через эпсилон - 722 микросекунд, всего совпадений = 4722020.08.1014:31:44.638 TestCompareDouble (USDCAD,H4) сравнение double через преобразование в int - 834 микросекунд, всего совпадений = 472
Não excluo que muito dependa da novidade e arquitectura do processador, e para alguém o resultado pode ser diferente.
Para dizer a verdade - nem sequer compreendo porque acontece. Parece que o compilador não tem nada a optimizar com a soma de números aleatórios. Não se pode colocar arredondamento de parênteses. Parece que a comparação dupla no processador é um comando Ao comparar através do epsilon (a forma mais rápida) ainda temos uma operação de comparação de dois duplos, mas além disso temos uma chamada de função com passagem de três parâmetros e uma operação de subtracção. O desempenho da operação de comparação de duas duplas depende dos valores das próprias variáveis? Duvido. Caramba, não percebo. Por favor, ajude-me, o que é que eu não tive em conta ou onde é que errei?
Apenas o arredondamento não é feito utilizando a ronda(), ceil(), chão() padrão, porque também devolvem o dobro.
Mas através destes, especialmente trabalham mais rapidamente do que os normais:
Pode ser mais rápido, mas é simplesmente errado.
Já o experimentou?
Experimente-o:
Produção:
deve ser 12346, porque é um tejadilho ("Retorna o valor numérico inteiro mais próximo de cima")o primeiro caso é 12345, porque os dígitos significativos em tipo duplo são 17, enquanto que tem 18
Realmente, não se podem comparar as duplas. É apenas uma regra difícil.
Naturalmente, é possível e por vezes até necessário comparar directamente entre si as duplas.
Por exemplo, o OnTick é por vezes chamado um trilião de vezes durante a Optimização. A fim de compreender se deve ou não executar um limite pendente, o testador incorporado compara o preço actual do símbolo correspondente e o preço limite. Fá-lo para cada encomenda pendente antes de cada chamada OnTick. Ou seja, estes controlos são feitos dezenas e centenas de milhares de milhões de vezes.
E é feito de cada vez através da normalização. Bem, isto é um desperdício horrível de recursos informáticos. Uma vez que os preços das encomendas pendentes e o símbolo são preliminarmente normalizados. Portanto, podem e devem ser comparados directamente uns com os outros.
O MQL-tester de MQL-personalizado tem um desempenho facilmente superior ao do testador nativo integrado em desempenho.
fxsaber:
Naturalmente, é possível e por vezes até necessário comparar directamente entre si as duplas.
Por exemplo, OnTick é por vezes chamado um trilião de vezes durante a Optimize. O testador incorporado, a fim de compreender se deve ou não executar um limite pendente, compara o preço actual do símbolo correspondente e o preço limite. Fá-lo para cada encomenda pendente antes de cada chamada OnTick. Ou seja, estes controlos são feitos dezenas e centenas de milhares de milhões de vezes.
E é feito de cada vez através da normalização. Bem, isto é um desperdício horrível de recursos informáticos. Uma vez que os preços das encomendas pendentes e o símbolo são preliminarmente normalizados. Portanto, podem e devem ser comparados directamente uns com os outros.
O MQL-tester de MQL-personalizado tem um desempenho facilmente superior ao do testador nativo integrado em desempenho.
NormalizeDouble() é uma função muito cara. Por conseguinte, é melhor esquecer isso.
Aqui está um guião que demonstra a diferença entre NormalizeDouble() e normalize com int:
resultado:
SZZ a normalização por int é também mais precisa (pode vê-la pelo número de noves após o último dígito da normalização - realçado a azul).NormalizeDouble() é uma função muito cara. É por isso que é melhor esquecê-lo.
Aqui está um guião que demonstra a diferença entre NormalizeDouble() e normalize com int:
resultado:
SZZ a normalização por int é ainda mais precisa (pode ver-se isto pelo número de noves após o último dígito da normalização - realçado a azul).e se a soma não é via dupla, mas via longa, então o resultado é ainda mais impressionante, visto que a soma via int (multiplicação e arredondamento seguido pela divisão da soma final) calcula mais rapidamente do que a soma normal da dupla.
resultado:
E se a soma não é via dupla, mas via longa, então o resultado é ainda mais impressionante, porque a soma via int (multiplicação e arredondamento, seguido pela divisão da soma total) é mais rápida do que uma soma dupla normal.
resultado:
Decimal para comparação adicionar.
Referência errada, não é uma implementação completa.
E é feito através da normalização de cada vez. Bem, isto é um terrível desperdício de recursos informáticos.
Como é que sabe? Porque mesmo que os preços não sejam normalizados, a verificação é simplesmente feita sem qualquer normalização:
Dado que os preços são múltiplos de carraças de tamanho
Além disso, a normalização através de int também se revela mais precisa (pode vê-la pelo número de noves após o último dígito de normalização - realçado a azul).
O teste está incorrecto. Porque se divide por 100000.0 apenas uma vez no final? Deve ser realizado em cada iteração e depois resumido. É uma comparação justa. Mas isto não é normalização de todo - acabou de optimizar o seu algoritmo de teste. Naturalmente, será mais rápido e mais preciso (porque o erro acumulado é reduzido).
Como é que sabe isto?
Porque pode introduzir preços não-normalizados ao Testador e este trata-os de forma idêntica.
Afinal, mesmo que os preços não estejam normalizados, a verificação é facilmente feita sem qualquer normalização.
Por normalização quis dizer neste caso, um único algoritmo padrão, após a sua aplicação, é possível comparar directamente duplicações deste padrão.
Assim, o testador não compara directamente as duplas. Fá-lo através de NormalizeDouble, ticksize ou qualquer outra coisa. Mas certamente não através da comparação directa de duplas. E não é de todo racional.
Naturalmente, é possível e por vezes mesmo necessário comparar directamente entre si as duplas.
Por exemplo, o OnTick é por vezes chamado um trilião de vezes durante a Optimize. O testador incorporado, a fim de compreender se deve ou não executar uma chamada de limite pendente, compara o preço actual do símbolo correspondente e o preço da chamada de limite. Fá-lo para cada encomenda pendente antes de cada chamada OnTick. Ou seja, estes controlos são feitos dezenas e centenas de milhares de milhões de vezes.
E é feito de cada vez através da normalização. Bem, isto é um desperdício horrível de recursos informáticos. Uma vez que os preços das encomendas pendentes e o símbolo são preliminarmente normalizados. Portanto, podem e devem ser comparados directamente uns com os outros.
O MQL-tester de MQL-personalizado não bate o testador nativo incorporado em desempenho.
Por isso, decidi verificar a versão sem sentido do desempenho.
E o resultado foi surpreendente.
A comparação até do dobro pré-normalizado é ainda mais lenta em média do que quando se compara o dobro através do epsilon ou conversão para int
O resultado:
Não excluo que muito dependa da novidade e arquitectura do processador, e para alguém o resultado pode ser diferente.
Para dizer a verdade - nem sequer compreendo porque acontece.
Parece que o compilador não tem nada a optimizar com a soma de números aleatórios. Não se pode colocar arredondamento de parênteses.
Parece que a comparação dupla no processador é um comando
Ao comparar através do epsilon (a forma mais rápida) ainda temos uma operação de comparação de dois duplos, mas além disso temos uma chamada de função com passagem de três parâmetros e uma operação de subtracção.
O desempenho da operação de comparação de duas duplas depende dos valores das próprias variáveis? Duvido.
Caramba, não percebo. Por favor, ajude-me, o que é que eu não tive em conta ou onde é que errei?