2010-03-11 9 views
18

(int)(33.46639 * 1000000) zurück 33466389Warum gibt (int) (33.46639 * 1000000) 33466389 zurück?

Warum passiert das?

+0

Was erwarten Sie passieren? – SLaks

+0

@Slaks: 3346639, aka, die richtige Antwort. –

+0

Guter Ort zum Starten: http://docs.sun.com/source/806-3568/ncg_goldberg.html (Was sollte jeder Informatiker über Gleitkommaarithmetik wissen) – mjv

Antwort

31

Fließkomma-Mathe ist nicht perfekt. What every programmer should know darüber.

Fließkommaarithmetik wird von vielen Menschen als esoterisches Thema angesehen. Dies ist ziemlich überraschend, weil Fließkomma-Systeme in Computersystemen allgegenwärtig sind. Fast jede Sprache hat einen Fließkomma-Datentyp; Computer von PCs zu Supercomputern haben Gleitkomma-Beschleuniger; Die meisten Compiler werden aufgefordert, von Zeit zu Zeit Fließkomma-Algorithmen zu kompilieren; und praktisch jedes Betriebssystem muss auf Gleitkommaausnahmen wie Überlauf reagieren. Dieser Artikel stellt ein Tutorial zu den Aspekten von Fließkomma vor, die sich direkt auf Designer von Computersystemen auswirken. Es beginnt mit einem Hintergrund zur Gleitkommadarstellung und einem Rundungsfehler, setzt sich mit einer Diskussion des IEEE-Gleitkommastandards fort und schließt mit zahlreichen Beispielen, wie Computerersteller Gleitkommaoperationen besser unterstützen können.

...

Squeezing unendlich vielen reellen Zahlen in eine endliche Anzahl von Bits erfordert, eine ungefähre Darstellung. Obwohl es unendlich viele Ganzzahlen gibt, kann in den meisten Programmen das Ergebnis von Ganzzahlberechnungen in 32 Bits gespeichert werden. Im Gegensatz dazu ergeben die meisten Berechnungen mit reellen Zahlen, die irgendeine feste Anzahl von Bits aufweisen, Größen, die unter Verwendung dieser vielen Bits nicht exakt dargestellt werden können. Daher muss das Ergebnis einer Gleitkommaberechnung oft gerundet werden, um wieder in seine endliche Darstellung zu passen. Dieser Rundungsfehler ist das charakteristische Merkmal der Gleitkommaberechnung.

+1

Es ist wahr, dass Fließkomma-Arithmetik sowohl allgegenwärtig als auch kompliziert ist, aber dies beantwortet die Frage nicht (es sei denn, Sie zählen die Verknüpfung zu einem 80-seitigen Papier, das die Antwort irgendwo hat). –

+2

@Henry - der Punkt ist im Titel des verknüpften Artikels. ** Jeder ** Programmierer sollte darüber Bescheid wissen, und wenn sie es nicht tun, sollten sie den Artikel lesen. (OK, vielleicht nicht alle 80 Seiten ...) –

+9

+1: Verknüpfung zu einem 80-Seiten-Papier, das irgendwo die Antwort hat, ist ein Standard-Anwser. Diese Frage wird - in der einen oder anderen Form - viel zu häufig gestellt. Dieses Papier ist * die * Antwort. Die Fragen sind alle Duplikate.Wir müssen diese Information nicht immer wieder wiederholen. –

5

doppelte Genauigkeit ist nicht exakt, so intern 33,46639 tatsächlich gespeichert als 33,466389

Edit: Wie Richard sagte, es Gleitkomma-Daten (gespeichert in binär in einer endlichen Menge von Bits), so ist es nicht genau das) ....

+1

oder 33.4668885 oder etwas anderes "nah genug", das sich darauf richtet, abhängig von der Hardware. – DaveE

+1

Ähm, keine der oben genannten. Es ist in der Basis 2. Die meisten solchen Zahlen können nicht genau in der Basis 10 ausgedrückt werden. (Ohne die Verwendung von unendlich wiederholten Ziffernfolgen sowieso. Ähnlich wie 1/3 als 0,33333 [inf] in der Basis 10 dargestellt werden muss.) –

+0

Fair genug , nicht genau das ... aber etwas näher als das Original. –

-1

Der Grund, warum Sie ein anderes Ergebnis bekam die Tatsache ist, dass Sie verwendet eine ‚ werfen‘

 
(int)(33.46639 * 1000000) returns 33466389 
^^^^^ 

das Ergebnis auf eine Art von ‚int‘ zu werfen ... die entweder aufzurunden oder unten den integralen Typ, wenn sie zusammen multipliziert werden und dann zu 'int' umgewandelt werden .... verlassen sich nicht auf Fließkomma, um genau genug zu sein .... Skeet veröffentlichte eine ausgezeichnete Einleitung auf seiner Site here und here ...

+0

Es gibt nichts an sich mit einem Casting verlustreich. Bibliotheken mit beliebiger Genauigkeit sind vorhanden. –

+0

Ich könnte mir vorstellen, dass er fragt: "Woher kam die 8 in meinem Ergebnis?" Das Multiplizieren mit 1000000 ist wie das Verschieben der 6 Dezimalstellen nach rechts, was "33466390" sein sollte, aber das ist nicht das, was er bekommt. Ihre Antwort ist, was ich anfangs dachte, bis ich die Frage noch einmal gelesen habe. – Pwninstein

+0

@Richard - wenn ein 'float' oder' double' Wert zu einem 'int' gezwungen wird, wird der Bruchteil verworfen, so dass Sie Informationen verlieren. – Seth

1

Wenn Sie fragen, warum nicht 33466390 werden, weil double s keine unendliche Genauigkeit haben, und die Zahl kann nicht genau in binär ausgedrückt werden.

Wenn Sie die double mit einem decimal ((int)(33.46639m * 1000000)) ersetzen, um es zu 33466390 gleich sein, weil decimal s in der Basis berechnet 10.

+0

Probleme wie diese sind Gleitkommazahlen, nicht nur binären Fließkommawerten, inhärent. Sicher, Dezimal wird 33,46639 * 1000000 richtig, aber immer noch 1/3 * 3! = 1 und pow (sqrt (2), 2)! = 2. – dan04

+0

Ja, aber sein spezifisches Problem ist aufgrund der binären. – SLaks

2

Der Grund dafür ist, dass 33,46639 wird als etwas etwas weniger als diese Zahl dargestellt werden .

Multiplikation mit 1000000 gibt Ihnen 33466389.99999999.

Typcasting mit (int) wird dann nur den ganzzahligen Teil (33466389) zurückgeben.

Wenn Sie die "richtige" Zahl wünschen, versuchen Sie, round() vor dem Casting.

+4

Whoa! ..... Nein nein Nein Nein Nein. Wenn Sie die Antwort "richtig" haben wollen, können Sie keine Fließkomma-Arithmetik verwenden. –

+4

Nein. Wenn Sie die "richtige" Antwort wünschen, können Sie keine * binäre * Fließkomma-Arithmetik verwenden. Verwenden Sie den Dezimal-Typ, der die Dezimal-Gleitkomma-Arithmetik verwendet, und es funktioniert wie erwartet. – Gabe

+1

33.46639 ist die "richtige" Antwort. Das Problem ist, dass der Fragesteller nicht die richtige Frage stellt. –

1

Da 33.46639 kann nicht genau in einer endlichen Anzahl von Binärziffern ausgedrückt werden. Das tatsächliche Ergebnis von 33,46639 * 1000000 ist 33466389.9999999962747097015380859375. Die Besetzung schneidet es auf 33466389.

+0

Versuchen Sie "kann nicht genau in einer endlichen Anzahl von gebrochenen binären Ziffern ausgedrückt werden" –

3

Es war Silvester am Ende des Jahres 1994. Andy Grove, CEO von Intel, kam aus einem großartigen Jahr, was mit dem Pentium-Prozessor kommen und ein großer Hit. Also ging er in eine Bar und bestellte eine Doppelaufnahme von Johnnie Walker Green Label.

Der Barkeeper servierte es und sagte, "das wird $ 20 sein, Sir."

Grove legte einen Zwanzig-Dollar-Schein auf die Theke, sah es für einen Moment an und sagte: "Behalten Sie die Veränderung."

http://en.wikipedia.org/wiki/Pentium_FDIV_bug

+0

Aber ... das ist eine ganze Zahl ... – Rawling

Verwandte Themen