2012-06-10 23 views
13
#include <stdio.h> 
#include <float.h> 

int main() 
{ 
    printf("%f\n", FLT_MAX); 
} 

salida de GNU:de impresión muy grandes números de punto flotante

340282346638528859811704183484516925440.000000 

salida desde Visual Studio:

340282346638528860000000000000000000000.000000 

¿Los estándares de C y C++ permiten que tanto los resultados? ¿O imponen un resultado específico?

Tenga en cuenta que FLT_MAX = 2^128-2^104 = 340282346638528859811704183484516925440.

+3

Los estándares C y C++ ni siquiera ordenan una representación de coma flotante específica. Así que estoy tentado de pensar que no pueden ordenar un resultado específico. – Mysticial

+0

@Mysticial Bueno, todavía podrían exigir que "se imprima el valor exacto que se representa" o algo por el estilo. – fredoverflow

+3

Y Unix pwns Windows. Una vez más. –

Respuesta

6

Creo que la parte pertinente de la norma C99 es la "práctica recomendada" de 7.19.6.1 p.13:

Para e, E, f, F, g y G conversiones, si el el número de dígitos decimales significativos es como máximo DECIMAL_DIG, luego el resultado debe redondearse correctamente. Si el número de dígitos decimales significativos es más de DECIMAL_DIG pero el valor de origen es exactamente representable con DECIMAL_DIG dígitos, el resultado debería ser una representación exacta con ceros al final. De lo contrario, el valor fuente está delimitado por dos cadenas decimales adyacentes L < U, ambos con DECIMAL_DIG dígitos significativos; el valor de la cadena decimal resultante D debe satisfacer L < = D < = U, con la estipulación adicional que el error debe tener una señal correcta para la dirección actual de redondeo.

Mi impresión es que esto permite algo de margen en lo que se puede imprimir en este caso; así que mi conclusión es que tanto VS como GCC son compatibles aquí.

+0

Erm ... ¿así es correcto GNU o Visual Studio? :) – fredoverflow

+2

Ambos son correctos, solo uno tiene más precisión. –

+5

@ColeJohnson: ninguno tiene más precisión. GNU te engaña para pensar que tiene, pero su resultado es incluso peor que el de MSVC. El punto flotante representa * intervalos *, no números. Así que 340282346638528859811704183484516925440, 340282346638528859811704183484516925450 y 340282346638528860000000000000000000000 tienen todos el mismo valor de coma flotante (para ieee de 64 bits). [Un mejor rountine de formato de punto flotante es en realidad el que le da la representación más corta posible] (http://florian.loitsch.com/publications/dtoa-pldi2010.pdf). – ybungalobill

1

Ambos están permitidos por la norma C (C++ simplemente Inports la norma C)

Desde un draft version en la sección 5.2.4.2.2 parte 10

Los valores dados en la lista siguiente será reemplazado por expresiones constantes con valores definido de implementación-de que son mayores que o iguales a los mostrados:
- máximo número flotante-punto representable infinito fl, (1 - b -p) b Emax

FLT_MAX 1E+37 

y C++ Visual 2012 tiene

#define FLT_MAX   3.402823466e+38F  /* max value */ 
+0

En la práctica, el valor de 'FLT_MAX' será el mismo en cualquier plataforma que use coma flotante IEEE-754. Entonces ese no es el problema aquí. –

+0

@OliCharlesworth: Bien, tal vez "defectuoso" es demasiado fuerte. Está invocando resultados indefinidos. – wallyk

0

El código en sí mismo es defectuoso donde utiliza %f para un valor mayor que la significación que tuvo lugar en un float o double. Al hacerlo, está pidiendo ver "detrás de la cortina" en cuanto a los bits de guardia sin sentido u otro ruido de punto flotante generado en la conversión a decimal.

Es evidente que no debe esperar ninguna consistencia en las limaduras de metal generadas después de fabricar un motor en Honda versus Toyota. No importa ninguna expectativa sensata de tal consistencia.

La forma correcta de mostrar dichos números es mediante el uso de uno de los formatos "científicos" como %g siempre que la precisión no esté sobreespecificada. En las implementaciones IEEE-754, 7 cifras decimales son significativas para float, 15-16 para double, aproximadamente 19 para long double, y 34 para __float128. Por lo tanto, para el ejemplo que ha proporcionado, %.15g sería apropiado, suponiendo que se encuentre en una implementación IEEE-754.

+1

Usar '% f' no es" defectuoso ". La pregunta es preguntar qué permite el estándar "detrás de las cortinas". –

+0

@OliCharlesworth: Bien, tal vez "imperfecto" es demasiado fuerte. Está invocando resultados indefinidos. – wallyk

Cuestiones relacionadas