Velocità di esecuzione delle funzioni ceil(),round(),floor() - pagina 6

 
Nikolai Semko:

Ne ho già scritto qui.

ok. come ho capito che stai scrivendo all'interno di questo terminale e all'interno della precisione data, non sei interessato a portare ed eseguire il codice su qualsiasi altro dispositivo o piattaforma.

Cordiali saluti.

P.S. Un buon programmatore dovrebbe capire che l'hardware e il programma possono cambiare ed è necessario evitare bug nel futuro.
 
Andrey Kisselyov:
Se state scrivendo nei limiti del terminale dato e nei limiti della sua precisione, il porting e il funzionamento del codice su qualsiasi altro dispositivo o piattaforma non vi interessa.

Sinceramente.

Esattamente. Stiamo parlando di MQL5 (forse anche di MQL4 - non ho controllato). E il codice all'interno delle classi o degli algoritmi sarà perfettamente portabile all'interno di MQL. Ma funzionerà anche in C++. Ho già alcuni esempi.

 
Andrey Kisselyov:

P.S. Un buon programmatore deve capire che l'hardware e il programma possono cambiare ed è necessario evitare errori in futuro. Con un compito come il tuo, potresti non essere in grado di trovare facilmente un errore in una funzione che considererai infallibile in quel momento.
In questa situazione è impossibile anche solo immaginare i cambiamenti di cui parli. Cosa potrebbe cambiare con la matematica del calcolo di (int)(x+0,5)? Smetterà di scartare la parte frazionaria o cosa?
 
Nikolai Semko:
In questa situazione, è impossibile anche solo immaginare i cambiamenti di cui parli. Cosa può cambiare con la matematica del calcolo (int)(x+0,5)? Smetterà di far cadere la parte frazionaria?

Per esempio, sarà introdotto un nuovo tipo di dati...

 
STARIJ:

Per esempio, sarà introdotto un nuovo tipo di dati...

))) Sì, ma il codice smetterà di funzionare se il vecchio tipo di dati è cancellato....
 
Sto parlando di questo casino.
y=(int)(x+0.9999999999999997);

Prendiamo come esempio:
se cambiate anche il bitness della macchina, passate a 64 bit e la precisione della macchina è aumentata, la vostra formula smetterà di funzionare perché la precisione della macchina sarà molto più alta di quella che state impostando nel vostro errore.

Con rispetto.

P.S. ci possono essere altre opzioni in cui la vostra formula fallirà su un intervallo di numeri. regolando costantemente l'errore dal passaggio a una macchina diversa, o cambiamenti nel compilatore, di cui non siete informati, o quando cambiate la rappresentazione dei numeri nella macchina, o dal taglio di una parte frazionaria del numero quando compilate una nuova versione del terminale... Non si sa cosa può cambiare, e non credo sia una buona idea fare un IF o soffrire per indovinare cosa succederà scrivendo un errore più e più volte...

Penso che sia qualcosa su cui riflettere.

 
Andrey Kisselyov:

...

P.S. Il doppio per definizione non può essere un intero, la rappresentazione di un numero nella memoria della macchina non cambia.

Forse stai dicendo che double non è un tipo di dati interi, non che non puoi memorizzare un numero con un valore intero in una variabile di tipo double? Un doppio intero può avere un valore intero.

 

Ho trovato una semplice spiegazione della differenza tra l'arrotondamento implementato nei computer e il semplice troncamento post-stack. Quattordici anni, http://delphimaster.net/view/14-10885/all:

Tolik(2003-08-13 11:04) [11].

Tale arrotondamento è accettato nella contabilità. Quindi, anche l'ufficio delle imposte applica questo arrotondamento, quindi tutto dovrebbe quadrare, almeno sulla carta :))



DiamondShark(2003-08-13 11:20) [12]

Oh-ho-ho... Di nuovo.
Supponiamo di avere una distribuzione di numeri quasi uniformemente casuale. Allora per arrotondamento "aritmetico" abbiamo:

Il numero Incertezza
0 0
1 -1
2 -2
3 -3
4 -4
5 +5
6 +4
7 +3
8 +2
9 +1

Come si può facilmente vedere, se c'è una grande serie di numeri che poi devono essere sommati (totali di voci di documenti, saldi di conti, ecc.), allora l'arrotondamento "aritmetico" accumulerà un errore sistematico con l'aspettativa
0,5*10^n * 0,1 * N
dove:
n -- peso decimale della cifra a cui viene eseguito l'arrotondamento (a due cifre n=-2, a interi n=0, ecc.)
0,1 è la probabilità di ogni cifra
N è un numero di interi in una matrice

Per equalizzare le probabilità di errore è necessario compensare l'unico errore non compensato (vedi tabella sopra) +5. Questo viene fatto dividendolo artificialmente in due +5 -5 ugualmente probabili a seconda della parità della cifra precedente.

Per inciso, c'è una casella di controllo nella parola di stato FPU che controlla la modalità di arrotondamento (aritmetico/contabile).


Fine della citazione.

Un altro, http://delphimaster.net/view/15-1340952214/all:"come l'utente medio (manager/contabile) non può spiegare perché arrotondare 12,5 e 13,5 - dà risultati diversi".


Quando si danno all'utente versioni "accelerate" di funzioni di arrotondamento, si deve avvertire fortemente che esse danno luogo a un errore maggiore quando si aggiunge. Questo errore dovrà essere valutato attentamente in situazioni molto diverse. È pericoloso, è irto di accumuli di errori. Trovo difficile pensare a un esempio in cui l'arrotondamento sia così importante da potersi dimenticare degli errori che accumula.

Округление чисел. Неужели ТАК правильно???
  • delphimaster.net
3-10545           Kati                  2003-08-12 10:13  2003.09.04   обновление SQL запроса 14-10898          kalishenko            2003-08-14 20:09  2003.09.04   Win2000 Server и доступ в Интернет 1-10692           lww                   2003-08-20 10:30  2003.09.04   Как написать dll для 1С? 1-10813           koks                  2003-08-20...
 

Andrey Kisselyov:
я говорю про вот это безобразие

y=(int)(x+0.9999999999999997);

Va bene, signori, avete espresso il vostro punto di vista. Cambierò la funzione ceil per te:

y=ceil(x);  ->  y=(x-(int)x>0)?(int)x+1:(int)x;
или через дефайн:
#define _ceil(x) (x-(int)x>0)?(int)x+1:(int)x

Questa variante è più lenta del 25-50% rispetto alla variante:y=(int)(x+0.999999999999999997); ma è massimamente corretta, funziona per gli interi negativi ed è 3 volte più veloce di ceil(x).

Ma io, come comune e fallito, userò la variante con i nove, perché considero tutti i vostri argomenti noiosi e per me, uno che ha programmato in assembler per molto tempo, e quindi sa cosa succede al codice dopo la compilazione, è troppo - mettere controlli dove si può fare a meno.

 

Una variante per i numeri positivi e negativi:

#define _ceil(x) (x-(int)x>0)?(int)x+1:(int)x
#define _round(x) (x>0)?(int)(x+0.5):(int)(x-0.5)
#define _floor(x) (x>0)?(int)x:((int)x-x>0)?(int)x-1:(int)x
Questo sembra essere un vero e proprio sostituto di ceil(),round(),floor(), che dà un vantaggio di velocità di 3-4 volte.
Motivazione: