2017-04-26 11 views
5

Die max Werte von int, float und lang in Scala sind:Was ist Int.MaxValue zwischen Freunden?

Int.MaxValue = 2147483647

Float.MaxValue = 3.4028235E38

Long.MaxValue = 9223372036854775807L

Von den Autoren des Scala-Compilers Keynote, PNW Scala 2013, Folie 16 What's Int.MaxValue between friends?:

val x1: Float = Long.MaxValue 
val x2: Float = Long.MaxValue - Int.MaxValue 
println (x1 == x2) 

// NO WONDER NOTHING WORKS 

Warum gibt dieser Ausdruck true zurück?

+0

kompilieren lässt, dass (die die Floating-Point-Codierung definiert)? Brauchen Sie keinen Gleichen nach 'x2'? – Carcigenicate

+0

Ich kann das nicht reproduzieren. Ich bekomme stattdessen einen Syntaxfehler. –

+1

Ich habe die Folie gefunden, die du erwähnt hast. Der Code, den Sie gepostet haben, unterscheidet sich von dem Code auf der Folie. Der Code auf der Folie weist den Syntaxfehler nicht auf. –

Antwort

10

Ein Float ist ein 4-Byte Gleitkommawert. Ein ist ein 8-Byte-Wert und ein Int ist auch ein 4-Byte-Wert. Wie Zahlen in 4-Byte-Fließkommawerten gespeichert werden, bedeutet jedoch, dass sie nur etwa 8 Stellen Genauigkeit haben. Folglich sind sie nicht in der Lage, selbst die 4 höchstwertigen Bytes (etwa 9-10 Stellen) eines Long zu speichern, ungeachtet des Werts der mindestens 4 signifikanten Bytes (weitere 9-10 Ziffern).

Folglich ist die Float Darstellung der beiden Ausdrücke gleich, weil die Bits, die sich unterscheiden, unter der Auflösung von Float liegen. Daher sind die beiden Werte gleich.

+3

Geben Sie +1 für das Schreiben einer Antwort, die jeden Drang vermeidet, einfach zu antworten "Fließkomma-Arithmetik saugt!" Wir alle wollten es. – ashawley

3

Echo Mike Allen Antwort, aber in der Hoffnung, einige zusätzliche Kontext (hätte dies als Kommentar, anstatt eine separate Antwort, aber SO Reputation Feature ließ mich nicht).

Integer haben einen maximalen Wertebereich von 0 bis 2^n (wenn es sich um eine Ganzzahl ohne Vorzeichen handelt) oder -2^(n-1) bis 2^(n-1) (für Ganzzahlen mit Vorzeichen) n ist die Anzahl der Bits in der zugrunde liegenden Implementierung (n = 32 in diesem Fall). Wenn Sie eine Zahl größer als 2^31 mit einem vorzeichenbehafteten Wert darstellen möchten, können Sie keinen int verwenden. Ein signiertes Long wird bis zu 2^63 funktionieren. Für etwas Größeres kann ein signierter Float bis zu 2^127 gehen.

Eine andere Sache zu beachten ist, dass diese Auflösungsprobleme nur in Kraft sind, wenn der Wert, der in der Fließkommazahl gespeichert wird, sich dem Maximum nähert. In diesem Fall verursacht die Subtraktionsoperation eine Änderung des wahren Werts, der viele Größenordnungen kleiner als der erste Wert ist. Ein Float würde den Unterschied zwischen 100 und 101 nicht abrunden, aber es könnte die Differenz zwischen 100000000000000000000000000000000 und 1000000000000000000000000000001 abrunden.

Das gleiche gilt für kleine Werte. Wenn Sie 0,1 in eine Ganzzahl umwandeln, erhalten Sie genau 0. Dies wird im Allgemeinen nicht als Fehler des Ganzzahl-Datentyps betrachtet.

Wenn Sie mit Zahlen arbeiten, die um viele Größenordnungen unterschiedlich sind und Rundungsfehler nicht tolerieren können, benötigen Sie Datenstrukturen und Algorithmen, die die inhärenten Einschränkungen der binären Datendarstellung berücksichtigen. Eine mögliche Lösung wäre, eine Gleitkomma-Codierung mit weniger exponentiellen Bits zu verwenden, wodurch der Maximalwert begrenzt wird, wobei jedoch für eine größere Auflösung weniger signifikante Bits bereitgestellt werden.Für weitere Einzelheiten finden Sie unter:

Verwandte Themen