Quero compartilhar uma descoberta inesperada, simples e útil com os programadores.
As funções de arredondamento:
Provaram ser muito lentos. Para acelerar o processo de arredondamento em 4-5 vezes (de acordo com meus testes em MQL5), você pode substituir estas funções por uma alternativa simples:
Como estas funções são freqüentemente utilizadas em laços grandes e aninhados, o ganho de desempenho pode ser bastante significativo.
Provavelmente, o fato de chamar uma função é bastante demorado (armazenamento de diferentes dados, endereços, etc.). E neste caso você pode passar sem funções.
Arquivo de roteiro com teste de desempenho anexado.
Somente eu com esta linha
y=round(x); -> y=(int)(x+0.5);
Não estou de acordo com esta linha. De acordo com as regras da matemática, se a parte fracionária for inferior a 0,5, o arredondamento é feito para o lado inferior. Mas se você acrescentar 0,5 a 45,27, ele é arredondado para o lado superior.
Só que eu não concordo com essa linha.
Eu não concordo. De acordo com as regras da matemática, se a parte fracionária for inferior a 0,5, ela é arredondada para baixo. Mas se você acrescentar 0,5 a 45,27, ele é arredondado para o lado superior.
#define MUL(x) ((x)+(0.5)) //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { ulong t0,t1,t2,t3; int y0[],y1[],y2[]; ArrayResize(y0,10000000); ArrayResize(y1,10000000); ArrayResize(y2,10000000); double x=1.45; for(int i=0;i<10000000;i++) { if ((int)(x+0.5)!=(int)round(x)) Print("ой...",x); x+=0.27; y0[i]+=0; y1[i]+=0; y2[i]+=0; } Print("y0[]: ",y0[9999999]," / y1[]: ",y1[9999999]," / y2[]: ",y2[9999999]); x=1.45; t0=GetMicrosecondCount(); for(int i=0;i<10000000;i++) { y0[i]=(int)MathRound(x); x+=0.27; } t1=GetMicrosecondCount()-t0; Print("y0[]: ",y0[9999999]); x=1.45; t0=GetMicrosecondCount(); for(int i=0;i<10000000;i++) { y1[i]=(int)(x+0.5); x+=0.27; } t2=GetMicrosecondCount()-t0; Print("y1[]: ",y1[9999999]); x=1.45; t0=GetMicrosecondCount(); for(int i=0;i<10000000;i++) { y2[i]=(int)MUL(x); x+=0.27; } t3=GetMicrosecondCount()-t0; Print("y2[]: ",y2[9999999]); Print("Цикл округления 10 000 000 раз: (round) = ",IntegerToString(t1)," альтернатива с (int) = ",IntegerToString(t2)," альтернатива с (#define) = ",IntegerToString(t3)," микросекунд"); } //+------------------------------------------------------------------+
Só que eu não concordo com essa linha.
Eu não concordo. De acordo com as regras da matemática, se a parte fracionária for inferior a 0,5, ela é arredondada para baixo. Mas se você acrescentar 0,5 a 45,27, ele é arredondado para o lado superior.
Você está confuso. Eu introduzi propositalmente um código de verificação no exemplo:
for(int i=0;i<10000000;i++) { if ((int)(x+0.5)!=(int)round(x)) Print("ой...",x); x+=0.27; }
Se eu estivesse errado, o operador deimpressão("oops...",x) seria executado;
Experimente - está tudo bem.
Eu sou o único com essa linha.
não concordam. De acordo com as regras da matemática, se a parte fracionária for inferior a 0,5, ela é arredondada para baixo. Mas se você acrescentar 0,5 a 45,27, ele é arredondado para o lado superior.
E que tal tomar e verificar? ))) Como int(45,27 + 0,5) daria 46? Os mesmos 45 permanecerão.
Eu não estava falando de velocidade.
Você deve estar confuso. Eu introduzi propositalmente um código de verificação no exemplo:
se eu estivesse errado, então a declaração deimpressão("oops...",x) seria executada;
Experimente - está tudo bem.
Mas ainda é interessante que a velocidade muda se a matriznão for preenchida com dados deantemão
#define _round(x) (int)((x)+(0.5)) //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { ulong t0,t1,t2; int y0[],y1[]; ArrayResize(y0,10000000); double x=1.45; for(int i=0;i<10000000;i++) { if ((int)(x+0.5)!=(int)round(x)) Print("ой...",x); x+=0.27; y0[i]+=0; // !!!!!!!!!!!!!! } x=1.45; t0=GetMicrosecondCount(); for(int i=0;i<10000000;i++) { y0[i]=(int)(x+0.5); x+=0.27; } t1=GetMicrosecondCount()-t0; x=1.45; t0=GetMicrosecondCount(); for(int i=0;i<10000000;i++) { y0[i]=_round(x); x+=0.27; } t2=GetMicrosecondCount()-t0; Print("Цикл округления 10 000 000 раз: с (int) = ",IntegerToString(t1)," с (#define) = ",IntegerToString(t2)," микросекунд"); } //+------------------------------------------------------------------+
e preenchidos
#define _round(x) (int)((x)+(0.5)) //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { ulong t0,t1,t2; int y0[],y1[]; ArrayResize(y0,10000000); double x=1.45; for(int i=1;i<10000000;i++) { if ((int)(x+0.5)!=(int)round(x)) Print("ой...",x); x+=0.27; y0[i]+=1; // !!!!!!!!!!!!!! } x=1.45; t0=GetMicrosecondCount(); for(int i=0;i<10000000;i++) { y0[i]=(int)(x+0.5); x+=0.27; } t1=GetMicrosecondCount()-t0; x=1.45; t0=GetMicrosecondCount(); for(int i=0;i<10000000;i++) { y0[i]=_round(x); x+=0.27; } t2=GetMicrosecondCount()-t0; Print("Цикл округления 10 000 000 раз: с (int) = ",IntegerToString(t1)," с (#define) = ",IntegerToString(t2)," микросекунд"); } //+------------------------------------------------------------------+
Que tal um teste? ))) Como int(45,27 + 0,5) daria 46? Os mesmos 45 permanecerão.
Concordo, perdi minha linha de raciocínio. Retiro o que disse...
Mas ainda é interessante que a velocidade muda se a matriznão for preenchida com dados deantemão
e preenchê-lo
y0[i]+=0; // !!!!!!!!!!!!!!
Eu acho "#define" mais conveniente
#define _floor(x) (int)((x)) #define _ceil(x) (int)((x)+(1)) #define _round(x) (int)((x)+(0.5))
Por que você não se lança ao longo do tempo? Embora você também possa transbordar, é muito mais fácil transbordar um Int.
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Quero compartilhar uma descoberta inesperada, simples e útil com os programadores.
As funções de arredondamento:
Provaram ser muito lentos. Para acelerar o processo de arredondamento em 4-5 vezes (de acordo com meus testes em MQL5), você pode substituir estas funções por uma alternativa simples:
Como estas funções são freqüentemente utilizadas em laços grandes e aninhados, o ganho de desempenho pode ser bastante significativo.
Provavelmente, o fato de chamar uma função é bastante demorado (armazenamento de diferentes dados, endereços, etc.). E neste caso você pode passar sem funções.
Arquivo de roteiro com teste de desempenho anexado.