El problema.C++ pérdida de precisión en punto flotante: 3015/0.00025298219406977296
compilador de Microsoft Visual C++ 2005, ventanas de 32 bits xp sp3, amd 64 x2 cpu.
Código:
double a = 3015.0;
double b = 0.00025298219406977296;
//*((unsigned __int64*)(&a)) == 0x40a78e0000000000
//*((unsigned __int64*)(&b)) == 0x3f30945640000000
double f = a/b;//3015/0.00025298219406977296;
el resultado del cálculo (es decir, "F") es 11917835,000000000 (((unsigned __int64) (& f)) == 0x4166bb4160000000) aunque debería ser 11,917,834.814763514 (es decir ((unsigned __int64) (& f)) == 0x4166bb415a128aef).
I.e. parte fraccional se pierde
Desafortunadamente, necesito que la parte fraccional sea correcta.
Preguntas:
1) ¿Por qué sucede esto?
2) ¿Cómo puedo solucionar el problema?
Otros detalles:
0) El resultado se toma directamente desde la ventana de "ver" (que no se imprimió, y no se olvidó de fijar la impresión de precisión). También proporcioné el volcado hexadecimal de la variable de coma flotante, por lo que estoy absolutamente seguro sobre el resultado del cálculo.
1) El desmontaje de f = a/b es:
fld qword ptr [a]
fdiv qword ptr [b]
fstp qword ptr [f]
2) f = 3015/0,00025298219406977296; rendimientos resultado correcto (f == 11917834,814763514, ((__int64 sin firmar) (& f)) == 0x4166bb415a128aef), pero parece que en este caso es simplemente resultado calculado durante el tiempo de compilación:
fld qword ptr [[email protected] (828EA0h)]
fstp qword ptr [f]
Así , ¿Como puedo solucionar este problema?
P.S. He encontrado una solución temporal (solo necesito una parte fraccional de la división, así que simplemente uso f = fmod (a/b)/b en este momento), pero aún me gustaría saber cómo solucionar este problema de manera adecuada: el doble se supone que la precisión es de 16 dígitos decimales, por lo que no se supone que este cálculo cause problemas.
Esta es una respuesta correcta. El programa usa Direct3D y, por supuesto, el cálculo ocurre después de la creación del dispositivo. Lo curioso es que sabía que D3D ajustaba la precisión de la FPU, pero me olvidé por completo, porque no he visto este error en los últimos años. Problema resuelto. – SigTerm
¿Qué indicador se debe usar al crear el dispositivo? ¿Existe el mismo problema con Direct2D? – dalle