No, esta no es otra pregunta "¿Por qué es (1 / 3.0) * 3! = 1" .
He estado leyendo mucho sobre puntos flotantes últimamente; específicamente, cómo el mismo cálculo podría dar diferentes resultados en diferentes arquitecturas o configuraciones de optimización.
Este es un problema para los videojuegos que almacenan repeticiones o están conectados en red entre pares (a diferencia del servidor-cliente), que dependen de que todos los clientes generen exactamente los mismos resultados cada vez que ejecutan el programa, una pequeña discrepancia en uno El cálculo de punto flotante puede conducir a un estado de juego drásticamente diferente en diferentes máquinas (¡o incluso en la misma máquina! )
Esto sucede incluso entre los procesadores que "siguen" IEEE-754 , principalmente porque algunos procesadores (concretamente x86) utilizan una precisión doblemente extendida . Es decir, usan registros de 80 bits para hacer todos los cálculos, luego se truncan a 64 o 32 bits, lo que lleva a resultados de redondeo diferentes que las máquinas que usan 64 o 32 bits para los cálculos.
He visto varias soluciones a este problema en línea, pero todas para C ++, no C #:
- Deshabilite el modo de doble precisión extendida (para que todos los
double
cálculos usen IEEE-754 de 64 bits) usando_controlfp_s
(Windows),_FPU_SETCW
(Linux?) Ofpsetprec
(BSD). - Siempre ejecute el mismo compilador con la misma configuración de optimización y requiera que todos los usuarios tengan la misma arquitectura de CPU (sin juego multiplataforma). Debido a que mi "compilador" es en realidad el JIT, que puede optimizar de manera diferente cada vez que se ejecuta el programa , no creo que esto sea posible.
- Utilice la aritmética de punto fijo, y evite
float
y pordouble
completo.decimal
funcionaría para este propósito, pero sería mucho más lento, y ninguna de lasSystem.Math
funciones de la biblioteca lo admite.
Entonces, ¿ es esto incluso un problema en C #? ¿Qué sucede si solo pretendo admitir Windows (no Mono)?
Si es así, ¿hay alguna forma de obligar a mi programa a ejecutarse con doble precisión normal?
Si no, ¿hay alguna biblioteca que ayude a mantener consistentes los cálculos de punto flotante?
strictfp
palabra clave, que obliga a todos los cálculos a realizarse en el tamaño indicado ( float
o double
) en lugar de un tamaño extendido. Sin embargo, Java todavía tiene muchos problemas con el soporte IEE-754. Muy (muy, muy) pocos lenguajes de programación admiten bien IEE-754.