2012-05-21 18 views
12

-freciprocal-math en GCC cambia el código siguiente¿Por qué -freciprocal-math no es seguro en GCC?

double a = b/c; 

a

double tmp = 1/c; 
double a = b * tmp; 

En manual de GCC, se dice que tal optimización es inseguro y no va pegada en los estándares IEEE. Pero no puedo pensar en un ejemplo. ¿Podría dar un ejemplo sobre esto?

+1

Considere b = c = 3 –

+0

No tengo IEEE tiene reglas sobre cómo un compilador debe usar el punto flotante. Por ejemplo, X^2 a menudo se reduce a X * X produciendo programas típicamente más rápidos pero con un error diferente que el cálculo especificado por el programador original. Entonces, @Kid, ¿has mirado el estándar IEEE para ver qué límites coloca en los compiladores que usan dicha aritmética? –

+0

@RaymondChen: después de que se aplica el redondeo IEEE (¿arriba? Abajo? Incluso? Ninguno?), ¿No es posible que su ejemplo b = c = 3 produzca exactamente el mismo resultado en a? –

Respuesta

12

Dividir por 10 y multiplicar por 0.1000000000000000055511151231257827021181583404541015625 no son lo mismo.

+0

Es cierto, no lo es. Pero el punto flotante tampoco te da una respuesta precisa si lo divides entre diez. Entonces, el argumento aquí parece ser cuánto error está dispuesto a aceptar en su aritmética de coma flotante. Si realiza flotante IEEE estándar, obtendrá una cierta cantidad de error en su cálculo (incluida la pérdida completa de precisión en determinadas circunstancias). Si realiza cálculos recíprocos, no obtiene un error de punto flotante definido por IEEE; si obtiene más o menos dependerá del cálculo real que esté haciendo. –

+1

@IraBaxter, división le da un resultado preciso si ambos operandos están representados exactamente, que serán para valores enteros. –

+0

@MarkRansom: Uh, ¿cómo obtengo un resultado preciso (¿quieres decir exactamente?) Para "1.0/3.0"? –

0

Tal vez estoy pensando en una bandera compilador diferente, pero ...

Algunos procesadores tienen instrucciones para calcular el recíproco aproximada. Me viene a la mente RCPSS om the x86 (instrucción SIMD); tiene un error relativo 1.5 * 2^-12. El uso de esa bandera puede permitirle al compilador seleccionar una instrucción recíproca aproximada, lo que podría no ser una acción segura dependiendo de su aplicación.

Espero que esto ayude.

+0

Con GCC, esta es la bandera -mrecip. – janneb

Cuestiones relacionadas