2015-06-05 4 views
9

Qualcuno può spiegarmi come funziona lo [.precision] in printf con l'identificatore "% g"? Sono abbastanza confuso dal seguente output:la precisione di printf con specificatore "% g"

double value = 3122.55; 
printf("%.16g\n", value); //output: 3122.55 
printf("%.17g\n", value); //output: 3122.5500000000002 

Ho imparato che %g utilizza la rappresentazione più breve.

Ma le seguenti uscite ancora mi confondono

printf("%.16e\n", value); //output: 3.1225500000000002e+03 
printf("%.16f\n", value); //output: 3122.5500000000001819 
printf("%.17e\n", value); //output: 3.12255000000000018e+03 
printf("%.17f\n", value); //output: 3122.55000000000018190 

La mia domanda è: perché %.16g dà il numero esatto, mentre %.17g non può?

Sembra che 16 cifre significative possano essere accurate. Qualcuno potrebbe dirmi il motivo?

+0

Non è mai così nei numeri a virgola mobile IEEE. – user35443

risposta

2

%g utilizza la rappresentazione più breve.

Numeri in virgola mobile nel computer aren't stored con la base di 10, ma 2. Ciò significa che di solito ci sono alcuni errori di arrotondamento, quando si rappresenta un numero decimale in un binario a virgola mobile.

Quando si specifica %.16g, si sta dicendo che si desidera la rappresentazione più breve con un massimo di 16 cifre significative significative.

Se la rappresentazione più breve ha più di 16 cifre, printf lo accorcia. Accorciamento si taglia il 2 alla fine, lasciandovi con 3122.550000000000, che è in realtà 3122.55 nella forma più breve, ecco perché il numero.

%g wil sempre dare il risultato più breve possibile, ma se dici che si desidera 17 luoghi di precisione, e l'° posto 17 contiene un valore diverso da 0, si finirà con tutti gli zeri e il valore al Alla fine: 3122.5500000000002.

La mia domanda è: perché %.16g dà il numero esatto, mentre %.17g non può?

E 'in realtà il %.17g che ti dà il risultato esatto, mentre %.16g ti dà solo un arrotondata approssimativo con un errore (se confrontato con il valore in memoria).

Se si desidera una precisione più precisa, utilizzare invece %f o %F.

+0

So che ci sono degli errori durante la presentazione di un float. Ciò che mi ha confuso è che sembra che le prime 16 cifre significative siano in realtà ciò che voglio senza errori di definizione. Perché? – cssmlulu

+0

@cssmlulu L'errore è al '17'. '% .16g' dice che ti preoccupi solo delle prime cifre' 16', e l'ultimo viene ignorato. Quando si hanno molti zeri (cifre non significative) alla fine, '% g' li taglia fuori, rendendolo così breve come' 3122.55'. – user35443

+2

@cssmlulu Oltre al commento di @ user35443, '% g' utilizza il numero di cifre significative come suo specificatore di precisione. È più spiegato qui: [Qual è la differenza tra% ge% f in C?] (Http://stackoverflow.com/a/5913115/4895040).Una regola con cifre significative indica che [TUTTI gli zeri tra numeri diversi da zero sono SEMPRE significativi.] (Http://www.usca.edu/chemistry/genchem/sigfig.htm), che si applica se usi '% .17g 'su' 3122.5500000000002' dato che gli zeri tra '5' e' 2' sono considerati significativi. Ecco perché questi zeri sono inclusi. – raymelfrancisco