Nein, dies ist keine weitere Frage "Warum ist (1 / 3.0) * 3! = 1" .
Ich habe in letzter Zeit viel über Gleitkomma gelesen; Insbesondere, wie dieselbe Berechnung auf verschiedenen Architekturen oder Optimierungseinstellungen zu unterschiedlichen Ergebnissen führen kann .
Dies ist ein Problem bei Videospielen, in denen Wiederholungen gespeichert sind oder die Peer-to-Peer-Netzwerke haben (im Gegensatz zu Server-Client), bei denen alle Clients bei jeder Ausführung des Programms genau dieselben Ergebnisse erzielen - eine kleine Diskrepanz in einem Gleitkommaberechnung kann auf verschiedenen Maschinen (oder sogar auf derselben Maschine! ) zu einem drastisch unterschiedlichen Spielzustand führen.
Dies geschieht sogar bei Prozessoren, die IEEE-754 "folgen" , hauptsächlich weil einige Prozessoren (nämlich x86) eine doppelt erweiterte Genauigkeit verwenden . Das heißt, sie verwenden 80-Bit-Register, um alle Berechnungen durchzuführen, und kürzen dann auf 64- oder 32-Bit, was zu anderen Rundungsergebnissen führt als Maschinen, die 64- oder 32-Bit für die Berechnungen verwenden.
Ich habe online mehrere Lösungen für dieses Problem gesehen, aber alle für C ++, nicht für C #:
- Deaktivieren Sie den Modus mit doppelter erweiterter Genauigkeit (damit alle
double
Berechnungen IEEE-754 64-Bit verwenden) mit_controlfp_s
(Windows),_FPU_SETCW
(Linux?) Oderfpsetprec
(BSD). - Führen Sie immer denselben Compiler mit denselben Optimierungseinstellungen aus und setzen Sie voraus, dass alle Benutzer dieselbe CPU-Architektur haben (kein plattformübergreifendes Spielen). Da mein "Compiler" eigentlich die JIT ist, die bei jeder Programmausführung möglicherweise anders optimiert wird , halte ich dies nicht für möglich.
- Verwenden Sie Festkomma-Arithmetik und vermeiden Sie
float
unddouble
insgesamt.decimal
würde für diesen Zweck funktionieren, wäre aber viel langsamer, und keine derSystem.Math
Bibliotheksfunktionen unterstützt dies.
Ist das überhaupt ein Problem in C #? Was ist, wenn ich nur Windows (nicht Mono) unterstützen möchte?
Wenn ja, gibt es eine Möglichkeit, mein Programm zu zwingen, mit normaler doppelter Genauigkeit ausgeführt zu werden?
Wenn nicht, gibt es Bibliotheken, die dazu beitragen , Gleitkommaberechnungen konsistent zu halten?
strictfp
Schlüsselwort, das alle Berechnungen in der angegebenen Größe ( float
oder double
) anstelle einer erweiterten Größe erzwingt . Java hat jedoch immer noch viele Probleme mit der IEE-754-Unterstützung. Sehr (sehr, sehr) wenige Programmiersprachen unterstützen IEE-754 gut.