2012-04-01 17 views
14

Como todos saben, tiene una precisión limitada cuando usa printf para generar el valor de float.
Sin embargo, hay un truco para aumentar la precisión en la salida, como muestra este ejemplo:Precisión de flotadores con printf

#include <stdio.h> 

int main() 
{ 
    float f = 1318926965;  /* 10 random digits */ 
    printf("%10.f\n", f);  /* prints only 8 correct digits */ 
    printf("%10d\n", *(int*)&f); /* prints all digits correctly */ 
    return 0; 
} 

y mi pregunta es, ¿por qué las personas no utilizan este truco más a menudo?

+1

Porque el comportamiento potencialmente indefinido es malo. (Editar: Técnicamente puede no ser un comportamiento indefinido, ya que no estoy seguro de lo que dice el estándar al respecto. Sin embargo, Endianess podría morderte con esto) – Corbin

+8

¡+1 para una buena broma de abril! – Henrik

+0

Aparentemente me consiguió x.x – Corbin

Respuesta

11

April fool?

Su "número aleatorio" 1318926965 tiene la misma representación subyacente tanto en forma decimal como en coma flotante.

Pruebe con otro valor, como 10. Se imprimirá como:

 10 
1092616192 

Así que para responder a su pregunta:

and my question is, why don't people use this trick more often? 

Debido a que sólo un día del año es día de los inocentes ... El resto de los días, el truco no funciona ...

4

Trate ese mismo truco con un número diferente, digamos 2318926965.

#include <stdio.h> 

int main() 
{ 
    float f = 2318926965;  /* 10 random digits */ 
    printf("%10.f\n", f);  /* prints only 8 correct digits */ 
    printf("%10d\n", *(int*)&f); /* prints all digits correctly */ 
    return 0; 
} 
$ gcc -Wall -O3 t.c 
t.c: In function ‘main’: 
t.c:7:5: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] 
$ ./a.out 
2318926848 
1326069764 

no veo un aumento en la precisión en absoluto con su "truco" que depende de la representación de bits de flotadores en su plataforma (por lo que yo lo entiendo).

This thread tiene algunos otros de estos "flotadores mágicos" y una forma de generarlos.

+0

Depende de la representación de bits de flotantes según IEEE 754, no "en su plataforma". (Modulo posibles problemas de orden de bytes que no existen en ninguna máquina del mundo real.) IMO lo único malo sobre código como este es el tipo incorrecto de juego de palabras que debería ser reemplazado por uniones (incompleto pero intencionalmente respaldado por todos los compiladores) o 'memcpy' (100% legal C). –

+0

Si IEEE 754 es obligatorio, ¿para qué sirve la definición '__STDC_IEC_559__'? – Mat

+0

No es obligatorio, pero considerando cuán roto el estándar C permite el punto flotante de las implementaciones no conformes con IEEE, y que no hay otra manera de que pueda decir en qué puede confiar respecto a la aritmética de coma flotante, lo consideraría un gran error para los programas que quieren ser portátiles a sistemas que no sean IEEE-math para usar punto flotante de cualquier tipo. (Naturalmente, sin embargo, podría usarlo en un programa no portátil destinado únicamente para su uso en una única implementación que no sea IEEE-math). –

0

El límite de precisión es con la representación de coma flotante, no con printf() es una premisa falsa.

Además, un solo flotador de precisión solo está garantizado con 6 dígitos de precisión, por lo que el "truco" sería engañarse a sí mismo; en el caso general, no funcionaría.

Si desea números de coma flotante de 10 dígitos, debe usar la precisión doble, que es válida para 15 dígitos.

Cuestiones relacionadas