2012-02-10 13 views
9

Esto es realmente un error extraño para mí y me tomó mucho tiempo descubrir qué está pasando. Para simplificar las cosas y reproducirse, basta con crear una aplicación de consola Win32 vacía usando VS2005 y utilizando un código en el método principal:¿Por qué el cálculo flotante y la conversión muestran resultados diferentes en la configuración de depuración y liberación?

float a = 411.00418f; 
float b = 1.0f; 
float c = 0.076279849f; 
unsigned short result = (unsigned short)((a-b)/c); 
unsigned short result2 = (unsigned short)((float)((a-b)/c)); 
// Debug: 5374, 5375 
// Release: 5374, 5374 
printf("%d, %d\n", result, result2); 

Por qué result2 muestra valor diferente en el modo de depuración/release?

Respuesta

10

En MSVC, el modo predeterminado de coma flotante es precise (/fp:precise). Lo que significa que el optimizador puede hacer ciertas optimizaciones para mejorar la precisión o el rendimiento.

Intente cambiar el modo a strict (/fp:strict). Esto hará que el compilador siga las estrictas reglas de coma flotante sobre el redondeo y demás.

(EDIT: strict (/fp:strict) no parece funcionar en este caso ...)

Si nos fijamos en el desmontaje de la estructura optimizada, se puede ver que todo el cálculo se ha doblado y optimizado a cabo.

push 5374     ; 000014feH 
push 5374     ; 000014feH 
push OFFSET [email protected][email protected][email protected] 
call DWORD PTR __imp__printf 
add esp, 12     ; 0000000cH 

EDIT: Esto parece un error de compilador optimizador para mí.

Bajo strict (/fp:strict), el siguiente código produce resultados diferentes:

float a = 411.00418f; 
float b = 1.0f; 
float c = 0.076279849f; 

unsigned short result1 = (unsigned short)((float)((a-b)/c)); 

float d = (float)((a-b)/c); 
unsigned short result2 = (unsigned short)(d); 

de salida:

5374, 5375 

tirando de la (float)((a-b)/c) en una asignación separada no debería afectar a los resultados bajo strict (/fp:strict).


Sé que uno de los chicos que trabajan en el optimizador MSVC. Le enviaré un informe de error.

Actualización:

He aquí su respuesta:

Hola Alex, gracias por este informe de error. Trataré de arreglar esto para la próxima versión de VC++ , pero podría no ser así.

Fwiw, el insecto no se reproduce si tiras/arch: SSE2, y ya que estamos permitiendo /arch: SSE2 por defecto para la próxima liberación de VC++ (https://connect.microsoft.com/VisualStudio/feedback/details/688736/compiler-generated-sse-instructions-without-arch-sse).

Por lo tanto, el comportamiento predeterminado mostrará que este error está solucionado. Pero si vuelves al antiguo modelo FP (throw/arch: IA32) la falla puede seguir presente.

Eric

así que han confirmado esto como un error.

+0

Establecí el "modelo de coma flotante" en "Estricto (/ fp: estricto)" y el resultado es el mismo. ¿Me perdí algo aquí? –

+0

Me di cuenta de eso también. Estoy tratando de resolverlo también. En la compilación optimizada, el optimizador está plegando todo el cálculo. Creo * que es allí donde no se respeta el comportamiento estricto de redondeo. – Mysticial

+0

En realidad, mi proyecto está usando C++/CLI en vs2010, entonces ¿eso también se ve afectado? –

Cuestiones relacionadas