2015-06-05 16 views
9

Czy ktoś może mi wyjaśnić, jak działa [.precision] w printf ze specyfikatorem "% g"? Jestem zupełnie zdezorientowany następujący wynik:precyzja printf ze specyfikatorem "% g"

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

Nauczyłem się, że %g wykorzystuje najkrótszą reprezentacji.

Ale następujące wyjścia nadal mi mylić

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 

Moje pytanie brzmi: dlaczego %.16g daje dokładną liczbę natomiast %.17g nie może?

Wygląda na to, że 16 cyfr znaczących może być dokładnych. Czy ktoś mógłby mi podać powód?

+0

Nigdy nie jest tak w liczbach zmiennoprzecinkowych IEEE. – user35443

Odpowiedz

2

%g używa najkrótszej reprezentacji.

Liczba zmiennoprzecinkowa w komputerze aren't stored z podstawą 10, ale 2. Oznacza to, że zwykle występują pewne błędy zaokrąglania, gdy reprezentują liczbę dziesiętną w binarnym zmiennoprzecinkowym.

Po określeniu %.16g mówisz, że chcesz najkrótszą reprezentację z maksymalnie 16 znaczącymi cyframi znaczącymi.

Jeśli najkrótsza reprezentacja ma więcej niż 16 cyfr, printf skróci to. Skrócenie spowoduje przecięcie 2 na końcu, pozostawiając Wam 3122.550000000000, która w rzeczywistości jest w najkrótszej postaci 3122.55, dlatego numer.

%g wil zawsze daje najkrótszą wynik możliwe, ale jeśli powiesz, że chcesz 17 miejsca precyzją, a th miejsce 17 zawiera jakąś wartość różną od 0, będziesz skończyć z wszystkich zer i wartości w koniec: 3122.5500000000002.

Moje pytanie brzmi: dlaczego %.16g daje dokładną liczbę while %.17g nie może?

To rzeczywiście %.17g co daje dokładny wynik, natomiast %.16g daje tylko przybliżone zaokrąglony z błędem (w porównaniu do wartości w pamięci).

Jeśli chcesz uzyskać bardziej stałą precyzję, użyj zamiast tego %f lub %F.

+0

Wiem, że występują błędy roudingowe podczas prezentacji float. To, co zdezorientowało mnie, to to, że wydaje się, że pierwsze 16 cyfr znaczących jest tym, czego chcę, bez błędu rouszowania. Czemu? – cssmlulu

+0

@cssmlulu Błąd występuje w '17'th. '% .16g' mówi, że zależy ci tylko na pierwszych cyfrach" 16 ", a ostatnia z nich jest ignorowana. Kiedy na końcu znajduje się dużo zer (nie znaczących cyfr), '% g' odcina je, czyniąc je tak krótkimi jak' 3122.55'. – user35443

+2

@cssmlulu Oprócz komentarza @ user35443, '% g' używa liczby cyfr znaczących jako specyfikatora dokładności. Bardziej wyjaśniono tutaj: [Jaka jest różnica między% g i% f w C?] (Http://stackoverflow.com/a/5913115/4895040).Jedna z liczb znaczących stwierdza, że ​​[ZERO między liczbami niezerowymi są ZAWSZE znaczące.] (Http://www.usca.edu/chemistry/genchem/sigfig.htm), które będą miały zastosowanie, jeśli użyjesz '% .17g 'na' 3122.5500000000002', ponieważ zera między '5' i' 2' są uważane za znaczące. Dlatego uwzględniono te zera. – raymelfrancisco