2016-04-15 11 views
8

Ich habe die folgende doppelte Berechnung in Java:Java Doppel verlierende Präzision Berechnung

double C1 = some value; // It's always an integer 
double C2 = some value; // It's always integer, and C2 >= C1 
double S = some value;  // It's always 0 < S <= 1 
double carry = some value; // It's always 0 <= carry < 1 

double rate = ((C1/C2)/S); 
double C3 = Math.floor((rate * S * C2) + carry); 

Nun, wenn wir nicht Präzision verlieren würde, würde C3 == C1 wahr sein. Aber da wir Präzision verlieren, werden C3 und C1 noch immer gleich sein?

Wenn sie nicht immer gleich sein würde, wenn ich C1 haben, C2, S und C3, wie konnte ich das rate ändern nach der Berechnung, um sicherzustellen, C3 würde C1 gleich sein?

Hinweis: Leider ist die Verwendung von BigDecimal keine Option.

+1

, wenn Sie daran interessiert sind, die Präzision zu halten, um eine 'BigDecimal' tun verwenden. – SomeJavaGuy

+0

Leider ist die Verwendung von BigDecimal keine Option, da die Rate bereits gespeichert ist, nachdem die Genauigkeit verloren gegangen ist, und ich kann nichts dagegen tun. – user1819676

+7

@KevinEsche BigDecimal verhindert nur den Verlust der Genauigkeit, wenn die Zahlen alle als abschließende Dezimalbrüche darstellbar sind. Betrachte den Fall von C1 = 1, C2 = 1, S = 0,3 –

Antwort

3

Im Allgemeinen vergleichen wir zwei Doppelwerte nicht direkt über ==. Stattdessen messen wir den Unterschied zwischen ihnen. z.B. Math.abs(C3 - C1) < 1e-6.

+0

Ja, wenn es darum ging, Doppel zu vergleichen. Aber die Funktion, die Math.floor ausführt, gibt eine ganze Zahl zurück. Sieh es dir so an. 'S' und' C2' sind in db gespeichert, und wir haben die Funktion, die in Zukunft zur Berechnung von C3 verwendet wird.Jetzt wollen wir 'rate' oder eine Änderung von' rate' in db speichern, um zu garantieren, dass die Funktion 'C3 == C1' generiert – user1819676

3

Nicht so.

Gleitkommazahl ist eine Annäherung. Das nächste Doppel, Bit 1, das zu der Mantisse hinzugefügt wird, kann eine ziemlich große Lücke für große Exponenten zwischen diesen zwei Doppelpunkten verursachen.

S, das 0 annähert, wird riesige Doppelgänger verursachen, die eine große Lücke zwischen ihnen haben. Das wird nicht mehr korrigierbar sein, sagen wir mit dieser einfachen Rundung. Auch wenn das kleine S nicht dazu führt, dass die Division mit INFINITY den doppelten Bereich überschreitet.

Man kann sich leicht von sein von 1000.