No, questa non è un'altra domanda "Why is (1 / 3.0) * 3! = 1" .
Ultimamente ho letto parecchi punti in virgola mobile; in particolare, come lo stesso calcolo potrebbe dare risultati diversi su architetture o impostazioni di ottimizzazione diverse.
Questo è un problema per i videogiochi che memorizzano replay o sono collegati in rete peer-to-peer (al contrario del server-client), che si affidano a tutti i client che generano esattamente gli stessi risultati ogni volta che eseguono il programma - una piccola discrepanza in uno il calcolo in virgola mobile può portare a uno stato di gioco drasticamente diverso su macchine diverse (o persino sulla stessa macchina! )
Ciò accade anche tra i processori che "seguono" IEEE-754 , principalmente perché alcuni processori (vale a dire x86) usano una doppia precisione estesa . Cioè, usano i registri a 80 bit per eseguire tutti i calcoli, quindi si troncano a 64 o 32 bit, portando a risultati di arrotondamento diversi rispetto alle macchine che usano 64 o 32 bit per i calcoli.
Ho visto diverse soluzioni a questo problema online, ma tutte per C ++, non C #:
- Disabilitare la doppia modalità di precisione estesa (in modo che tutti i
double
calcoli utilizzino IEEE-754 a 64 bit) utilizzando_controlfp_s
(Windows),_FPU_SETCW
(Linux?) Ofpsetprec
(BSD). - Esegui sempre lo stesso compilatore con le stesse impostazioni di ottimizzazione e richiedi a tutti gli utenti di avere la stessa architettura della CPU (nessuna riproduzione multipiattaforma). Poiché il mio "compilatore" è in realtà il JIT, che può ottimizzare in modo diverso ogni volta che il programma viene eseguito , non penso che sia possibile.
- Usa l'aritmetica in virgola fissa, ed evita
float
e deldouble
tutto.decimal
funzionerebbe a questo scopo, ma sarebbe molto più lento e nessuna delleSystem.Math
funzioni di libreria lo supporta.
Quindi, questo è anche un problema in C #? Cosa succede se intendo supportare solo Windows (non Mono)?
In tal caso, esiste un modo per forzare l'esecuzione del mio programma alla normale doppia precisione?
In caso contrario, ci sono librerie che potrebbero aiutare a mantenere coerenti i calcoli in virgola mobile?
strictfp
parola chiave, che impone che tutti i calcoli vengano eseguiti nella dimensione dichiarata ( float
o double
) anziché in una dimensione estesa. Tuttavia, Java ha ancora molti problemi con il supporto IEE-754. Pochissimi (molto, molto) pochi linguaggi di programmazione supportano bene IEE-754.