2012-04-01 15 views
14

Come tutti sanno, la precisione è limitata quando si utilizza printf per produrre il valore di float.
Tuttavia, c'è un trucco per aumentare la precisione nella produzione, come mostra questo esempio:Precisione di galleggianti 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; 
} 

e la mia domanda è, perché le persone non usano questo trucco più spesso?

+1

Perché il comportamento potenzialmente non definito è negativo. (Modifica: tecnicamente potrebbe non essere un comportamento indefinito, dato che non sono sicuro di quello che dice lo standard. Endianess potrebbe morderti con questo però.) – Corbin

+8

+1 per una buona battuta di aprile! – Henrik

+0

A quanto pare mi ha dato x.x – Corbin

risposta

11

April fool?

Il "numero casuale" 1318926965 ha la stessa rappresentazione di base sia in forma decimale che in virgola mobile.

Provare un altro valore, ad esempio 10. Sarà stampata come:

 10 
1092616192 

Quindi, per rispondere alla tua domanda:

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

Perché solo un giorno dell'anno è aprile Fools Day ... Il resto dei giorni il trucco non funziona ...

4

Prova lo stesso trucco con un numero diverso, dire 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 

non vedo un aumento della precisione a tutti con il "trucco" che dipende dalla rappresentazione po ' di galleggianti sulla tua piattaforma (per quanto ho capito).

This thread ha alcuni altri di questi "magici galleggianti" e un modo per generarli.

+0

Dipende dalla rappresentazione bit di float per IEEE 754, non "sulla tua piattaforma". (Modulo possibili problemi di ordine dei byte che non esistono su nessuna macchina del mondo reale.) IMO l'unica cosa negativa di codice come questo è la puntura di tipo improprio che dovrebbe essere sostituita con i sindacati (abbozzati ma volutamente supportati da tutti i compilatori) o 'memcpy' (100% legale C). –

+0

Se IEEE 754 è obbligatorio, a cosa serve la definizione __STDC_IEC_559__'? – Mat

+0

Non è obbligatorio, ma considerando quanto rotto lo standard C permetta il virgola mobile delle implementazioni non-IEEE, e che non c'è altro modo in cui puoi dire su cosa puoi fare affidamento per quanto riguarda l'aritmetica in virgola mobile, la considererei un enorme errore per i programmi che vogliono essere portabili a sistemi matematici non IEEE per utilizzare il floating point di qualsiasi tipo. (Naturalmente è possibile utilizzarlo su un programma non portatile destinato esclusivamente a un'implementazione matematica non IEEE.) –

0

Il limite di precisione è con la rappresentazione in virgola mobile, non con printf() è una premessa errata.

Inoltre un singolo galleggiante di precisione è garantito solo con precisione a 6 cifre di precisione, quindi il "trucco" potrebbe ingannare te stesso; nel caso generale non funzionerebbe.

Se si desidera utilizzare numeri a virgola mobile a 10 cifre, è necessario utilizzare la doppia precisione, che vale per 15 cifre.

Problemi correlati