Implementazioni alternative di funzioni/approcci standard - pagina 10

 
pavlick_:
)). Questo può avere un posto solo nei mestieri personali con una conoscenza esatta della gamma di valori, ma non nella biblioteca std. Le funzioni integrate non sono scritte da sciocchi, non pensate di essere i più intelligenti. Ecco un amico che scrive anche comportamenti indefiniti e non specificati e poi si sorprende che non funziona così https://www.linux.org.ru/forum/development/14422428#comments. Tutti questi risparmi di qualche nanosecondo non saranno nemmeno visibili nell'algoritmo reale (non nel ciclo nudo).

Solo ora ho capito cosa stavi dicendo.
Ritiro che non sei nel giro. Chiedo scusa.
Sì, potete usare questa variante con la condizione che il numero doppio si trovi nell'intervallo da -9007199254740992 a 9007199254740992 (2 alla potenza di 53 (numero di bit nella mantissa))

 
Renat Fatkhullin:
Pensate a quello che otterrete al di fuori della gamma dei numeri interi.

che ne dici di questo?

double Ceil (double x) { return double((x>9007199254740992 || x<-9007199254740992 )?x:(x-(long)x>0)?(long)x+1:(long)x);}
double Round(double x) { return double((x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)(x+0.5):(long)(x-0.5));}
double Floor(double x) { return double((x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)x:((long)x-x>0)?(long)x-1:(long)x);}

risultato:

2018.08.26 10:49:23.552 TestRound (Crypto.ALT,M10)      Время цикла без округления = 1.317 наносекунд, сумма = 115583114403605978808320.00000000
2018.08.26 10:49:23.556 TestRound (Crypto.ALT,M10)      Время выполнения функции ceil =  2.129 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.557 TestRound (Crypto.ALT,M10)      Время выполнения функции Ceil =  0.100 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.560 TestRound (Crypto.ALT,M10)      Время выполнения функции floor = 1.299 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.561 TestRound (Crypto.ALT,M10)      Время выполнения функции Floor = 0.120 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.564 TestRound (Crypto.ALT,M10)      Время выполнения функции round = 1.787 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.566 TestRound (Crypto.ALT,M10)      Время выполнения функции Round = 0.106 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.566 TestRound (Crypto.ALT,M10)      Идет бесконечный поиск расхождения по случайным числам double ... Прервите скрипт, когда надоест ждать

il test sembra mostrare un'identità completa.

Tuttavia, la velocità della soluzione alternativa in questo caso, dove c'è un controllo dell'intervallo, è superiore di circa 2 volte (invece di 3-8), ma questo è se il numero doppio è nell'intervalloda -9007199254740992 a 9007199254740992. Ma è molto più alto quando è al di fuori di questo intervallo.

File:
TestRound.mq5  9 kb
 
Nikolai Semko:


il test sembra mostrare un'identità completa.

Tuttavia, questa variante non tiene conto dell'overflow della variabile di inputdi tipo doppio, quando prende i valori nan, snan.

Se si deve tenerne conto, si può aggiungere un ulteriore controllo, ma comunque questa variante funzionerà più velocemente della funzione originale

double Ceil (double x) { return double((!MathIsValidNumber(x) || x>9007199254740992 || x<-9007199254740992 )?x:(x-(long)x>0)?(long)x+1:(long)x);}
double Round(double x) { return double((!MathIsValidNumber(x) || x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)(x+0.5):(long)(x-0.5));}
double Floor(double x) { return double((!MathIsValidNumber(x) || x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)x:((long)x-x>0)?(long)x-1:(long)x);}
 
Nikolai Semko:

Scrivere un EA per un tester/ottimizzatore. È qui che la velocità nella pratica è importante.

 
fxsaber:

Scrivere un EA per un tester/ottimizzatore. È qui che la velocità è importante nella pratica.

Come molti sanno, mi occupo anche di grafica liscia. È per lisciare la grafica e lavorare con ogni pixel che le funzioni di arrotondamento sono attivamente utilizzate.

Prima non potevo nemmeno immaginare che la funzione di arrotondamento fosse più lenta dell'estrazione della radice quadrata del doppio.
È per questo motivo che ho preso a soffocare quei nanosecondi. Perché quei nanosecondi sul grafico lisciato possono trasformarsi in millisecondi su ogni frame, e un frame può cambiare ogni 33 millisecondi.

 
Nikolai Semko:

Come molti sanno, mi occupo anche di grafica anti-alias. È per la grafica anti-alias e per lavorare con ogni pixel che le funzioni di arrotondamento sono utilizzate attivamente.
È per questo che mi sono impegnato a smussare quei nanosecondi. Perché quei nanosecondi sulla grafica levigata possono trasformarsi in millisecondi su ogni frame, e un frame può cambiare ogni 33 millisecondi.

Naturalmente, questo è importante per la grafica. Ecco perché le ottimizzazioni algoritmiche per quasi tutti i compiti comuni esistono da molto tempo.

 
fxsaber:

Naturalmente, questo è importante per la grafica. Ecco perché le ottimizzazioni algoritmiche per quasi tutti i compiti comuni esistono da molto tempo.

Vi sbagliate. Il campo non è ancora arato, e quello che è arato è chiuso. E in MQL ancora di più. La classe CCanvas è molto lontana dall'ottimalità e non c'è quasi nessun antialiasing e quello che c'è di antialiasing è insoddisfacente.

 

Perché non usate LONG_MAX/MIN? Sarebbe più bello in qualche modo. Ha un bell'aspetto, credo. Ho eseguito i tuoi test con gcc (con min modifica, naturalmente, molto vecchio compilatore 5.4.0, quello che avevo a portata di mano):

1. Compilazione con -O3.

Время цикла без округления = 0.001099185 секунд, сумма = 1.15583114 e+23
Время выполнения функции ceil =  0.004310106 секунд, сумма = 1.15583114 e+23
Время выполнения функции Ceil =  0.001912712 секунд, сумма = 1.15583114 e+23
Время выполнения функции floor =  0.005283493 секунд, сумма = 1.15583114 e+23
Время выполнения функции Floor =  0.002031304 секунд, сумма = 1.15583114 e+23
Время выполнения функции round =  0.005308409 секунд, сумма = 1.15583114 e+23
Время выполнения функции Round =  0.002344382 секунд, сумма = 1.15583114 e+23

2. Compilazione con -Ofast

Время цикла без округления = 0.000552652 секунд, сумма = 1.15583114 e+23
Время выполнения функции ceil =  0.001720999 секунд, сумма = 1.15583114 e+23
Время выполнения функции Ceil =  0.00189282 секунд, сумма = 1.15583114 e+23
Время выполнения функции floor =  0.001430063 секунд, сумма = 1.15583114 e+23
Время выполнения функции Floor =  0.001979336 секунд, сумма = 1.15583114 e+23
Время выполнения функции round =  0.001698521 секунд, сумма = 1.15583114 e+23
Время выполнения функции Round =  0.001944874 секунд, сумма = 1.15583114 e+23

Il tuo codice ha un problema con il calcolo del tempo - l'output è in millisecondi (non nano), e ancora non capisco perché hai bisogno di meno t0.

Print("Время выполнения функции ceil =  "+DoubleToString((double)(GetMicrosecondCount()-t-t0)/1000,3)+" наносекунд, Контрольная сумма = "+string(s));
 
Nikolai Semko:

Sbagliato. C'è ancora un campo non arato, e quello che è arato è chiuso.

Parlavo di esperienza mondiale. Guarda gli algoritmi sui forum tematici dove fanno demo di grafici. Le persone stanno condividendo i loro algoritmi veloci.

 
fxsaber:

Parlavo di esperienza mondiale. Cerca gli algoritmi nei forum tematici dove si fanno le demo dei grafici. Le persone stanno condividendo algoritmi veloci.

Puoi mandarmi il link per favore?
Motivazione: