2009-07-20 11 views
5

Intentando portar código Java a C++ He tropezado con un comportamiento extraño. No puedo obtener una doble adición al trabajo (aunque la opción del compilador/fp: strict, que significa matemática "correcta" de coma flotante, se establece en Visual Studio 2008).¿Por qué los dobles se agregan incorrectamente en un proyecto específico de Visual Studio 2008?

double a = 0.4; 
/* a: 0.40000000000000002, correct */ 

double b = 0.0 + 0.4; 
/* b: 0.40000000596046448, incorrect 
(0 + 0.4 is the same). It's not even close to correct. */ 

double c = 0; 
float f = 0.4f; 
c += f; 
/* c: 0.40000000596046448 too */ 

En un proyecto de prueba diferente que estableció que funciona bien (/ fp: se comporta de acuerdo con los estrictos IEEE754).

Uso de Visual Studio 2008 (estándar) sin optimización y FP: estricto.

¿Alguna idea? ¿Realmente está truncando a las carrozas? Este proyecto realmente necesita el mismo comportamiento tanto en Java como en C++. Obtuve todos los valores leyendo desde la ventana de depuración en VC++.

Solución: _fpreset(); // La idea de Barry Kelly lo resolvió. Una biblioteca estaba estableciendo la precisión de FP en bajo.

+2

¿Se puede publicar un pequeño programa de prueba completo junto con la línea de comando exacta utilizada para compilar (ver ventana de salida, etc.), que demuestra el problema? La única forma en que puedo reproducir es usando 0.0f + 0.4f en su lugar. –

+0

¿Podemos suponer que conoce la imprecisión de los tipos de coma flotante? Tener una precisión de 7 decimales generalmente se considera correcto ya que la precisión de impresión predeterminada es 6. –

+0

@Evan, su ejemplo está desactivado por más de lo que se explicaría por la imprecisión en coma flotante. – Kevin

Respuesta

8

Lo único que se me ocurre es que quizás estés enlazando con una biblioteca o DLL que ha modificado la precisión de la CPU a través de la palabra de control.

¿Ha intentado llamar al _fpreset() desde float.h antes del cálculo problemático?

+0

Debe ser algo así, pero ¿es 0.0 + 0.4 incluso un cálculo? ¿No se puede evaluar en tiempo de compilación? Verificar el desmontaje podría establecer si el modo de flotación de tiempo de ejecución tiene algo que ver con eso o si algo salió mal en el momento de la compilación. –

+0

Claro que puede ser, pero si fuera así de simple, sería fácil de reproducir, ¿no? –

+0

No sé, tal vez algo más en el proyecto sea especificar/fp: estúpido o equivalente. Mi favorito personal sería un archivo fuente no terminado en línea nueva y, por lo tanto, el programa tiene un comportamiento indefinido, aunque no tengo muchas esperanzas de ver que cause un error en la naturaleza ... –

3

Sí, ciertamente es truncar a las carrozas. Obtengo el mismo valor de impresión float f = 0.4 que en el caso "impreciso". Pruebe:

double b = 0.0 + (double) 0.4; 

La pregunta es por qué está truncado a las carrozas. No hay excusa en el estándar para tratar 0.0 + 0.4 como una expresión de precisión única, ya que los literales de coma flotante son de doble precisión a menos que tengan un sufijo para decir lo contrario.

Así que algo debe estar interfiriendo con su configuración, pero no tengo ni idea de qué.

Cuestiones relacionadas