2010-01-04 18 views
7

Ich bin auf diese Werte in meinem ColdFusion-Code gestoßen, aber der Google-Rechner scheint denselben "Bug" zu haben, bei dem der Unterschied nicht null ist.Warum ist diese Subtraktion nicht gleich Null?

416582,2850 bis 411476,8100 - 5105,475 = -2.36468622461E-011

http://www.google.com/search?hl=en&rlz=1C1GGLS_enUS340US340&q=416582.2850+-+411476.8100+-+5105.475&aq=f&oq=&aqi=

diese lang/float JavaCast'ing/double es nicht Hilfe- führt zu anderen Nicht-Null Unterschiede.

+16

Es sollte ein Fließkomma-Quiz beim Erstellen eines Kontos auf SO geben. Ich denke, das ist die am häufigsten gestellte Frage auf der Website. – recursive

+3

@recursive: http://meta.stackexchange.com/questions/26621/whats-the-most-repeated-question-on-stackoverflow/26633#26633 –

+1

Wenn ich gelernt habe zu programmieren, der Mangel an Genauigkeit in Gleitkommazahlen Es wurde erwähnt, dass das erste Mal Floating Point diskutiert wurde, und danach mehrmals. Tun sie das nicht mehr? –

Antwort

16

Dies liegt daran, dass Dezimalzahlen, die in der Basis 10 "rund" aussehen, in Basis 2 nicht genau dargestellt werden können (was Computer zur Darstellung von Gleitkommazahlen verwenden). Eine ausführliche Erläuterung dieses Problems und der Problemumgehungen finden Sie im Artikel What Every Computer Scientist Should Know About Floating-Point Arithmetic.

+1

5105.475 war die Zahl, die nicht genau in einem Doppel darstellbar war. PrecisionEvaluate ist die ColdFusion-Funktion, die ich brauchte. –

+0

Tatsächlich ist keine dieser Zahlen genau als doppelte Genauigkeitswerte darstellbar. –

+0

+1 ausgezeichnete Referenz, auch "Wie Gleitkommazahlen genau gedruckt" von GL Steele –

7

Gleitkomma-Ungenauigkeiten (es gibt eine unendliche Anzahl von reellen Zahlen und nur eine endliche Anzahl von 32- oder 64-Bit-Zahlen, um sie darzustellen). Wenn Sie mit kleinen Fehlern nicht umgehen können, sollten Sie statt dessen BigDecimal verwenden.

+1

Referenz: http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems –

+0

Aber 416582.2850 - 411476.8100 kann * genau * als 5105.475 dargestellt werden. Dies sind Zahlen mit nur 4 Dezimalstellen, die sich nicht wiederholen. Sind 4 Dezimalstellen zu genau? –

+2

Es ist nicht die Basis-10-Darstellung, die endlich sein muss, es ist die Basis-2-Darstellung. Unter http://en.wikipedia.org/wiki/Binary_numeral_system#Fractions_in_binary finden Sie eine Erklärung, welche Brüche genau im Binärformat dargestellt werden können (es sind nur diejenigen, die 2 als Primfaktor des Nenners haben). –

1

Das Problem ist die ungenaue Darstellung von Fließkommatypen. Da diese nicht genau als Floats dargestellt werden können, erhalten Sie einen gewissen Präzisionsverlust, der dazu führt, dass Vorgänge kleine Fehler aufweisen. Normalerweise möchten Sie mit floats vergleichen, ob das Ergebnis innerhalb eines kleinen epislon (Fehlerfaktors) einem anderen Wert entspricht.

2

Da Computer Zahlen im Binärformat speichern, sind die Gleitkommazahlen ungenau. 1E-11 ist ein kleiner Unterschied, da diese Dezimalzahlen auf die nächste darstellbare Binärzahl gerundet werden.

2

Dieser "Bug" ist kein Fehler. So funktioniert Fließkommarechnung. Siehe: http://docs.sun.com/source/806-3568/ncg_goldberg.html

Wenn Sie beliebiger Genauigkeit wollen in Java verwenden BigDecimal:

BigDecimal a = new BigDecimal("416582.2850"); 
    BigDecimal b = new BigDecimal("411476.8100"); 
    BigDecimal c = new BigDecimal("5105.475"); 
    System.out.println(a.subtract(b).subtract(c)); // 0.0 
1

Diese werden Gleitkomma-Probleme und mit BigDecimal werden es beheben.

Ändern der Reihenfolge der Subtraktion ergibt auch Null in Google.

416582.2850 - 5105.475 - 411476.8100 = 0 
5

Verwenden PrecisionEvaluate() in Coldfusion

zero = PrecisionEvaluate(416582.2850 - 411476.8100 - 5105.475); 

im Gegensatz zu Evaulate(), keine "" benötigt wird (es BigDecimal in Java verwenden werden).

+1

+1 für die tatsächliche kalte Fusion Lösung – Kip

Verwandte Themen