2012-04-09 18 views
20

Wenn ich mit einer double arbeite, und ich konvertiere es in eine float, wie funktioniert das genau? Wird der Wert abgeschnitten, sodass er in einen Float passt? Oder wird der Wert anders gerundet? Entschuldigung, wenn das ein wenig Abhilfe klingt, aber ich versuche, das Konzept der float und double Konvertierungen zu begreifen.Konvertieren von Double in Float in Java

+0

http://StackOverflow.com/a/2781125/986169 – giorashc

Antwort

19

Vom Java Language Specification, section 5.1.3:

Eine Verengung primitive Umwandlung von Doppel zu schweben wird geregelt durch die IEEE 754 Rundungsregeln (§4.2.4). Diese Umwandlung kann die Genauigkeit verlieren, aber auch die Entfernung verlieren, was zu einer Float-Null von einem Nicht-Null-Doppel und einer Float-Unendlichkeit von einem endlichen Doppel führt. Ein Doppel-NaN wird in ein Float-NaN umgewandelt, und ein Doppel-Unendlich wird in die Float-Unendlichkeit mit demselben Vorzeichen umgewandelt.

und section 4.2.4 sagen:

Die Java-Programmiersprache erfordert, dass Gleitkomma-Arithmetik verhalten, als ob jeder Floating-Point-Betreiber sein Fließkommaergebnis auf das Ergebnis Genauigkeit gerundet. Ungenaue Ergebnisse müssen auf den darstellbaren Wert gerundet werden, der dem unendlich genauen Ergebnis am nächsten kommt; Wenn die beiden nächstliegenden darstellbaren Werte gleich sind, wird diejenige mit dem niedrigstwertigen Bit Null gewählt. Dies ist der standardmäßige Rundungsmodus des IEEE 754-Standards, der als "Rund" zum nächsten bezeichnet wird.

+0

Danke dafür. Ich habe bemerkt, dass es die Verwendung von IEEE 754 Runde zum nächsten erwähnt. Gibt es trotzdem einen anderen Rundungsmodus? – Franklin

+0

@Franklin: Es gibt eine ['RoundingMode'] (http://docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html) Klasse, aber ich denke das gilt nur für' BigDecimal' und "BigInteger" -Operationen, nicht Operationen auf Primitiven. Aber ich bin nicht hundertprozentig zuversichtlich. –

+1

Java unterstützt nur einen fp-Rundungsmodus - es wurde darüber geredet, vor einigen Jahren etwas hinzuzufügen (vor allem für die HPC-Community, also auch für den Umgang mit Denorms usw.), aber leider ging das nirgendwohin. – Voo

8

Ich würde vorschlagen, dass Fließkommatypen am sinnvollsten als Wertebereiche dargestellt werden. Der Grund, dass 0,1f als 0,1 anstatt als 0,100000001490116119384765625 angezeigt wird, ist, dass es tatsächlich den Zahlenbereich von 13421772.5/134217728 bis 13421773.5/134217728 (d. H. Von 0.0999999977648258209228515625 bis 0.1000000052154064178466796875) darstellt; es wäre nicht sinnvoll, zusätzliche Ziffern hinzuzufügen, die anzeigen, dass die Zahl größer als 0,100 ist, wenn es weniger sein kann, oder eine Zeichenfolge von Neun zu verwenden, die angibt, dass die Zahl kleiner als 0,100 ist, wenn sie größer sein könnte.

Wenn Sie einen Double-Wert in einen Float-Wert umwandeln, wird der Float-Wert ausgewählt, dessen Wertebereich den doppelten Bereich des Double-Werts enthält. Beachten Sie, dass, während diese Operation nicht umkehrbar ist, das Ergebnis der Operation im Allgemeinen arithmetisch korrekt ist; das einzige Mal, wenn es nicht zu 100% arithmetisch korrekt wäre, wäre es, wenn man einen Doppelgänger werfen würde, dessen Bereich genau auf der Grenze zwischen zwei Schwimmern zentriert war. In dieser Situation würde das System den Schwimmer auf der einen oder der anderen Seite des Doppelbereichs auswählen; Wenn das Doppelte tatsächlich eine Zahl auf der falschen Seite des Bereichs darstellt, wäre die resultierende Umwandlung etwas ungenau.

In der Praxis ist die oben erwähnte winzige Ungenauigkeit fast nie relevant, weil der "Wertebereich", der durch einen Fließkommatyp dargestellt wird, in der Praxis etwas größer ist als oben angegeben. Wenn Sie eine Berechnung (z. B. Addition) an zwei Zahlen mit einer bestimmten Unsicherheit durchführen, erhalten Sie ein Ergebnis mit größerer Unsicherheit, aber das System behält nicht den Überblick darüber, wie groß die Unsicherheit ist. Nichtsdestoweniger, wenn man Dutzende von Operationen an einem Float oder Tausende von Operationen an einem Double durchführt, ist die Menge an Unsicherheit normalerweise klein genug, um sich keine Sorgen zu machen.

Es ist wichtig zu beachten, dass das Float-Floating zu einem Double weitaus gefährlicher ist als Double Float, obwohl Java das erstere implizit ohne Warnung erlaubt, aber bei letzterem quatscht. Wenn Sie einen Float-Wert auf einen Double-Wert setzen, wählt das System das Double aus, dessen Bereich um den Mittelpunkt des Float-Bereichs zentriert ist. Dies führt fast immer zu einem Wert, dessen tatsächliche Unsicherheit viel größer ist, als dies für Zahlen mit doppelter Genauigkeit typisch wäre. Zum Beispiel, wenn man 0 wirft.1f, um zu verdoppeln, wird das resultierende Doppel eine Zahl im Bereich von 0,10000000149011611 bis 0,10000000149011613 darstellen, obwohl die Zahl, die es darstellen soll (ein Zehntel) relativ weit entfernt ist.