Voglio condividere con i programmatori una scoperta inaspettata, semplice e utile.
Le funzioni di arrotondamento:
Hanno dimostrato di essere molto lenti. Per accelerare il processo di arrotondamento di 4-5 volte (secondo i miei test in MQL5), potete sostituire queste funzioni con una semplice alternativa:
Poiché queste funzioni sono spesso utilizzate in cicli grandi e annidati, il guadagno di prestazioni può essere abbastanza significativo.
Probabilmente, il fatto di chiamare una funzione richiede molto tempo (memorizzazione di diversi dati, indirizzi, ecc.). E in questo caso si può fare a meno delle funzioni.
File di script con test di performance allegato.
Solo io con questa linea
y=round(x); -> y=(int)(x+0.5);
Non sono d'accordo con questa linea. Secondo le regole della matematica, se la parte frazionaria è inferiore a 0,5, l'arrotondamento viene fatto al lato inferiore. Ma se si aggiunge 0,5 a 45,27, si arrotonda al lato superiore.
Solo che non sono d'accordo con questa linea.
Non sono d'accordo. Secondo le regole della matematica, se la parte frazionaria è inferiore a 0,5, viene arrotondata per difetto. Ma se si aggiunge 0,5 a 45,27, si arrotonda al lato superiore.
#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)," микросекунд"); } //+------------------------------------------------------------------+
Solo che non sono d'accordo con questa linea.
Non sono d'accordo. Secondo le regole della matematica, se la parte frazionaria è inferiore a 0,5, viene arrotondata per difetto. Ma se si aggiunge 0,5 a 45,27, si arrotonda per eccesso.
Sei confuso. Ho volutamente inserito un codice di verifica nell'esempio:
for(int i=0;i<10000000;i++) { if ((int)(x+0.5)!=(int)round(x)) Print("ой...",x); x+=0.27; }
Se mi fossi sbagliato, verrebbe eseguito l'operatorePrint("oops...",x);
Provalo - va bene.
Sono l'unico con quella linea.
non sono d'accordo. Secondo le regole della matematica, se la parte frazionaria è inferiore a 0,5, viene arrotondata per difetto. Ma se si aggiunge 0,5 a 45,27, si arrotonda al lato superiore.
Che ne dite di prenderlo e controllarlo? ))) In che modo int(45.27 + 0.5) darebbe 46? Gli stessi 45 rimarranno.
Non stavo parlando di velocità.
Devi essere confuso. Ho volutamente inserito un codice di controllo nell'esempio:
se mi fossi sbagliato, sarebbe stata eseguita l'istruzionePrint("oops...",x);
Provalo - va bene.
Ma è ancora interessante che la velocità cambia se l'arraynon èriempito di datiin anticipo
#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 riempito
#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)," микросекунд"); } //+------------------------------------------------------------------+
Che ne dite di un test? ))) In che modo int(45.27 + 0.5) darebbe 46? Gli stessi 45 rimarranno.
Sono d'accordo, ho perso il filo del discorso. Mi rimangio tutto...
Ma è ancora interessante che la velocità cambia se l'arraynon è riempito di datiin anticipo
e riempirlo
y0[i]+=0; // !!!!!!!!!!!!!!
Trovo che "#define" sia più conveniente
#define _floor(x) (int)((x)) #define _ceil(x) (int)((x)+(1)) #define _round(x) (int)((x)+(0.5))
Perché non lanci alla lunga? Sebbene si possa anche traboccare, è molto più facile traboccare un Int.
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso
Voglio condividere con i programmatori una scoperta inaspettata, semplice e utile.
Le funzioni di arrotondamento:
Hanno dimostrato di essere molto lenti. Per accelerare il processo di arrotondamento di 4-5 volte (secondo i miei test in MQL5), potete sostituire queste funzioni con una semplice alternativa:
Poiché queste funzioni sono spesso utilizzate in cicli grandi e annidati, il guadagno di prestazioni può essere abbastanza significativo.
Probabilmente, il fatto di chiamare una funzione richiede molto tempo (memorizzazione di diversi dati, indirizzi, ecc.). E in questo caso si può fare a meno delle funzioni.
File di script con test di performance allegato.