Non, ce n'est pas une autre question "Pourquoi est (1 / 3.0) * 3! = 1" .
J'ai beaucoup lu sur les virgules flottantes ces derniers temps; plus précisément, comment le même calcul peut donner des résultats différents sur différentes architectures ou paramètres d'optimisation.
C'est un problème pour les jeux vidéo qui stockent des rediffusions, ou qui sont en réseau peer-to-peer (par opposition au serveur-client), qui reposent sur tous les clients générant exactement les mêmes résultats à chaque fois qu'ils exécutent le programme - une petite différence dans un. le calcul en virgule flottante peut conduire à un état de jeu radicalement différent sur différentes machines (ou même sur la même machine! )
Cela se produit même parmi les processeurs qui «suivent» IEEE-754 , principalement parce que certains processeurs (notamment x86) utilisent une double précision étendue . Autrement dit, ils utilisent des registres de 80 bits pour effectuer tous les calculs, puis tronquent à 64 ou 32 bits, ce qui conduit à des résultats d'arrondi différents de ceux des machines qui utilisent 64 ou 32 bits pour les calculs.
J'ai vu plusieurs solutions à ce problème en ligne, mais toutes pour C ++, pas C #:
- Désactivez le mode double précision étendue (afin que tous les
double
calculs utilisent IEEE-754 64 bits) à l'aide de_controlfp_s
(Windows),_FPU_SETCW
(Linux?) Oufpsetprec
(BSD). - Exécutez toujours le même compilateur avec les mêmes paramètres d'optimisation et exigez que tous les utilisateurs aient la même architecture de processeur (pas de jeu multiplateforme). Parce que mon "compilateur" est en fait le JIT, qui peut s'optimiser différemment chaque fois que le programme est exécuté , je ne pense pas que cela soit possible.
- Utilisez l'arithmétique à virgule fixe, et évitez
float
etdouble
tout à fait.decimal
fonctionnerait dans ce but, mais serait beaucoup plus lent, et aucune desSystem.Math
fonctions de la bibliothèque ne le prend en charge.
Alors, est-ce même un problème en C #? Que faire si je compte uniquement prendre en charge Windows (et non Mono)?
Si tel est le cas, existe-t-il un moyen de forcer mon programme à s'exécuter en double précision normale?
Sinon, existe-t-il des bibliothèques qui permettraient de maintenir la cohérence des calculs en virgule flottante?
strictfp
mot - clé, qui force tous les calculs à être effectués dans la taille indiquée ( float
ou double
) plutôt que dans une taille étendue. Cependant, Java a encore de nombreux problèmes avec le support IEE-754. Très (très, très) peu de langages de programmation prennent bien en charge IEE-754.