2014-09-12 8 views
5

Kann jemand erklären, warum hier ein Unterschied im Verhalten ist?Warum sprintet der Sprint um den Bruchteil von 5.555 und 0.555 anders?

perl -E 'say sprintf("%.2f",5.555);' 
5.55  

perl -E 'say sprintf("%.2f",0.555);' 
0.56 

Ich habe gelesen, dass sprintf() Runden, wenn die folgenden Ziffern 5 oder höher. Also, warum reiht es sich im zweiten Fall nicht auf 0,56 auf?

+1

Sehr gute Antworten sind hier http://StackOverflow.com/Q/24493228/632407 – jm666

+1

Auf eine verwandte Anmerkung, 'sprintf' Runden auf gerade, so' sprintf '% .0f', 0.5' gibt '0' und 'sprintf '% .0f', 1.5 'ergibt' 2', obwohl '0.5' und' 1.5' genau wie eine Fließkommazahl dargestellt werden können. – ikegami

Antwort

9

Die nächste IEEE 754 64-Bit-Floating-Point-Check Nummer bis 0,555 ist 0,55500000000000004884981308350688777863 979339599609375. Es liegt sehr nahe bei 0,56 als bei 0,55.

Die nächste IEEE 754 64-Bit-Binär-Gleitkommazahl zu 5.555 ist 5.55499999999999971578290569595992565155029296875. Es liegt etwas näher bei 5,55 als bei 5,56.

In jedem Fall ist der Ausgang die nächste Dezimalstelle mit 2 Dezimalstellen zum tatsächlichen Wert der internen Zahl.

wie Pascal Cuoq in einem Kommentar sagt, ist 0.555 in der binade [0,5 ... 1), in der darstellbaren Gleitkommazahlen um 2 -53 getrennt sind. Im Gegensatz dazu liegt 5.555 in der binade [4 ... 8], in der darstellbare Gleitkommazahlen durch 2 -50 getrennt sind. Aus diesem Grund sind die Bruchzahlen für 0,555 und 5,555 unterschiedlich.

+0

+ 1.Wie wussten Sie über diese Darstellung? – Jim

+1

@Jim Ich habe Java verwendet: 'System.out.println (new BigDecimal (0,555));', aber es gibt viele Möglichkeiten, dies zu tun, einschließlich Webseiten. –

+0

Ich verstehe nicht, was diese '0,555 ist in der binade [0,5 ... 1), bedeutet. Kannst du es mir bitte erklären? – Jim

5

Da printf den Wert rundet, versuchen Sie einfach:

perl -e 'printf("%.25f", 5.555)' 

gibt:

5.5549999999999997157829057 

gerundet auf 5.55 mit printf('%.2f', 5.55)

und

perl -e 'printf("%.25f", 0.555)' 

gibt

0.5550000000000000488498131 

gerundet auf 0.56 mit printf('%.2f', 0.55)

+0

Warum hast du .25f gemacht? Wie hast du diese 25 ausgewählt? – Jim

+0

@Jim: Es ist nur ein Beispiel, um sicher zu sein, viel Dezimal zu haben, Sie könnten das gleiche mit '% .10' – Toto

+0

+ 1.So im Grunde war die Idee, einen großen Formatierer zu verwenden, so dass die Zahl erweitert zu sehen die tatsächliche Darstellung? – Jim

1

Wenn Sie konsistentere Ergebnisse wollen, Math::Round

perl -MMath::Round=:all -E 'say nearest(.01, 0.555)' 
0.56 

perl -MMath::Round=:all -E 'say nearest(.01, 5.555)' 
5.56 
+0

Ist diese Bibliothek aktiv? Sie wurde im Jahr 2000 erstellt.Sorry, aber aufgrund meines Hintergrunds weiß ich nicht, wie die Perl-Bibliotheken verwaltet/unterstützt werden – Jim

+0

@Jim es wurde danach aktualisiert http://search.cpan.org/~ grommel/Math-Round-0.06/ –

+0

Auch das Update ist 2006.Wie kann man wissen, ob es von vielen Nutzern aktiv genutzt wird? – Jim