Java Double-Werte ungenau?

limoneneis

Cadet 4th Year
Registriert
Okt. 2009
Beiträge
72
Hi,

ich habe Programm entwickelt, dass Transaktionen abwickelt. Ich habe mal einen Geschäftstag simuliert. Dabei werden für verschiedene Akteure Double-Werte <5.0 festgelegt und es bilden sich im Tagesverlauf andere Werte in Abhängig der Aktionen anderer Akteure. Die Rechenoperationen sind einfache plus- und minus-rechnungen - davon aber sehr viele.

Pro Stunde fallen pro Akteuer 7000 dieser Rechenoperationen an.

Kann es sein, dass dabei die Genauigkeit flöten geht? Am Ende des Tage müsste wieder 0 herauskommen. Ich habe aber Abweichungen von ca. ~(+,-) 0.05. Ist damit zu rechnen oder muss in meinem Quelltext den Fehler finden?

gruß
 
Ist ganz normal, ist bei fließkommazahlen so, das beste ist du rechnest in centbeträgen mit int, oder du nimmst nur die ersten 2 nachkommastellen, kann aber auch zu ungenauigkeiten führen.
 
Das ist normal. Für genaue Rechnungen mit Fließkommazahlen verwendet man die Methoden der Klasse java.math.BigDecimal.
 
Jup ist normal. Gab sogar mal vor ein paar Jahren hier bei der Deutschen Bank den Fall, das sich ein Programmierer diese rundungs und Rechenungenauichkeiten auf sein eigenes Konto überwiesen hat^^

Ich nehme für so was in Java auch immer BigDecimal. Ist sogar extra dafür gedacht.
hier steht die Dokumentation der Klasse und warum das normale rechnen Fehler erzeugt:
http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/java_zehnerrechnen_de
 
Zuletzt bearbeitet:
Hallo

Danke für die Antworten. Ich habe es mal mit BigDecimal versucht, jedoch habe ich nur sehr marginale verbesserungen. Kann es sein, dass wenn man einen BigDecimal wert durch einen double-wert gewinnt und den BigDecimal-Wert nach den rechenoperationen wieder in ein Double-Wert umwandelt, dass dann die Genauigkeit wieder weg ist?

Code:
BigDecimal b = new BigDecimal(doubleWert + "");

// (...) Rechenoperation

double returnMe = b.doubleValue(); //Passiert hier das übel?

gruß
 
Ja? Der Hinweg reicht ja schon. Und über den Rückweg werden evtl. nochmals Informationen verloren, je nachdem, ob die Zahl als double darstellbar ist.
 
Wo ist das Problem einfach int zu nehmen, wenn es um Geld geht? Ich bin im Bauspar- und -finanzierungsbereich tätig und hier wird in diesem Fall ausschließlich int verwendet.
 
Du könntest ne Klasse "Geld" machen mit variablen "Euro" und "Cent", und dann so Sachen wie geld1.add(geld2) und geld1.normalize() definieren. Letzteres könnte dann zB Sachen wie 2 Euro 104 Cent in 3 Euro 4 Cent umrechnen... :D

Ist aber vielleicht auch zuviel des Aufwands...

Vielleicht einfach intern mit Cent als int rechnen, würde ich auch machen.

Du kannst es dir ja mal anschauen, was zB bei 1 Euro 2 Cent passiert: http://www.wolframalpha.com/input/?i=1,02_2

Es wird im Binärsystem periodisch, und ist somit nicht exakt darstellbar. Damit gibt es einen Fehler in der Größe der Maschinenungenauigkeit/Datentyp.
 
Zuletzt bearbeitet:
character schrieb:
Wo ist das Problem einfach int zu nehmen, wenn es um Geld geht? Ich bin im Bauspar- und -finanzierungsbereich tätig und hier wird in diesem Fall ausschließlich int verwendet.
Versuch das mal an einer Tankstelle...
 
limoneneis schrieb:
Hallo

Danke für die Antworten. Ich habe es mal mit BigDecimal versucht, jedoch habe ich nur sehr marginale verbesserungen. Kann es sein, dass wenn man einen BigDecimal wert durch einen double-wert gewinnt und den BigDecimal-Wert nach den rechenoperationen wieder in ein Double-Wert umwandelt, dass dann die Genauigkeit wieder weg ist?

Code:
BigDecimal b = new BigDecimal(doubleWert + "");

// (...) Rechenoperation

double returnMe = b.doubleValue(); //Passiert hier das übel?

gruß

Du solltest dann natürlich auch BigDecimal als Ein- und Ausgabewert haben damit die Genauigkeit erhalten bleibt.

http://docs.oracle.com/javase/6/docs/api/java/math/BigDecimal.html#doubleValue()
Note that even when the return value is finite, this conversion can lose information about the precision of the BigDecimal value.

@kuddlmuddl
BigDecimal ist ein BigInteger Wert welcher bei zusätzlich angegeben ist wo ich der Decimalpunkt befindet.
A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale. If zero or positive, the scale is the number of digits to the right of the decimal point. If negative, the unscaled value of the number is multiplied by ten to the power of the negation of the scale. The value of the number represented by the BigDecimal is therefore (unscaledValue × 10-scale).
Warum Probleme lösen für die es schon Lösungen gibt?
 
Also wenn ihr für Finanzen in einer Bank int verwendet dann hoffe ich dass es nicht auch so in meiner Bank ist. Bin zwar nicht reich aber will nichts mit einer Bank zu tun haben die nur rund 21 millionen +/- bearbeiten können.
 
Dann hätte er wohl mal lieber dazu schreiben sollen das er von int64 redet.
Bitte nicht falsch verstehen aber wenn man wem schon etwas erklärt, etc dann sollte man vorsichtig sein das man keine Missverständnisse zulässt.
Im Allgemeinen sollte man vielleicht nochmal erwähnen das in der Finanzbranche sicher nicht mit zwei Kommastellen gearbeitet wird. Nachdem allein schon penystocks mehr verwenden.
 
Ein Integer ist ein Integer. Du betreibst dabei einfach nur haarspalterei, dass ein 64 Bit Integer nicht unter dem Begriff Integer verstanden werden würde. Jeder halbwegs intelligente Entwickler wird bei so einer Aussage von character natürlich ein Integer mit der passenden Bitbreite nehmen, wir sind ja im Normalfall keine Vollhonks.
 
Zurück
Oben