Mit dem double rechnen

Hallo Leute,

es soll eine Formel entwickelt werden, die mit double hantiert,
was wäre aus mathematischer Sicht für die meisten Fälle/Werte genauer:

        
        double d1 = 1.0 / 6.0 * 100.0; // 16.666666666666664

        // oder
        
        double d2 = 1.0 * 100.0 / 6.0; // 16.666666666666668```

Also
a / b * c
oder
a * c / b
was wäre präferrilich (wobei c = 100.0)?

Hat nix mit meinem Nick zu tun. ;)

Freundliche Grüße

Manche Leute würden jetzt auf https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html verweisen, ggf. sogar in einer Form, die suggeriert, sie würden dem Titel zustimmen und sich selbst als “Computer Scientists” sehen. Tatsächlich ist die Frage aus theoretischer Sicht ganz interessant, und ich habe gerade tatsächlich mal rumprobiert, weil mich diese “4” etwas irritiert hat

        System.out.println(1.0 / 6.0 * 100.0); // 16.666666666666664
        System.out.println(1.0 * 100.0 / 6.0); // 16.666666666666668
        
        System.out.println(1.0 / 600.0 * 10000.0); // 16.666666666666668
        System.out.println(1.0 * 10000.0 / 600.0); // 16.666666666666668        

        System.out.println(1.0 / 60000.0 * 1000000.0); // 16.666666666666668
        System.out.println(1.0 * 1000000.0 / 60000.0); // 16.666666666666668
        
        System.out.println(1.0 / 6000000.0 * 100000000.0); // 16.666666666666668
        System.out.println(1.0 * 100000000.0 / 6000000.0); // 16.666666666666668        
        
        System.out.println(1.0 / 600000000000000000000000000.0 * 10000000000000000000000000000.0); // 16.666666666666664 !!!
        System.out.println(1.0 * 10000000000000000000000000000.0 / 600000000000000000000000000.0); // 16.666666666666668        
        
        System.out.println(1.0 / 6000000000000000000000000000000000000000000.0 * 100000000000000000000000000000000000000000000.0); // 16.666666666666668 !!!
        System.out.println(1.0 * 100000000000000000000000000000000000000000000.0 / 6000000000000000000000000000000000000000000.0); // 16.666666666666668        

aber praktisch spielt das kaum eine Rolle. Einmal ist der Fehler dessen, was angezeigt wird 2.6… * 10^-15, und einmal 1.3…*10^-15, also
0.0000000000000026666… vs
0.0000000000000013333…

Ansonsten der übliche Link… java - Why does changing the sum order returns a different result? - Stack Overflow (bezieht sich auf Summen, aber bei Produkten ist es ähnlich)

Also ist es sinnvoller, mit größeren double zu rechnen, wenn man die Wahl hat?
Ich dachte, double sei im Bereich [0, 1] genauer als z. B. (1, 100]?
Wieso ist’s so?

Und wenn man später rundet, dann ist 16.666666666666664 ~= 16.66666666666666 und 16.666666666666668 ~= 16.66666666666667. Was ist denn nun genauer?
Beschwichtigend muss ich hinzufügen, dass ich mir die Links bislang nicht durchlesen konnte.

Die Geschichte der Genauigkeit ist eine Geschichte voller Mißverständnisse :smiley:

Ich bin da auch nicht mehr so „drin“, und maße mir nicht an, die Details aus dem Goldberg-Artikel parat zu haben. Aber ein häufiges Mißverständnis ist, dass die Genauigkei von float/double-Werten mit der Größe der Zahl zusammenhängt. Die Probleme entstehen hauptsächlich, wenn man sehr unterschiedlich große Zahlen miteinander verrechnet - und auch da entstehen die meisten Probleme bei Addition und Subtraktion. Ansonsten ist der Unterschied zwischen
0.123
und
0.0000000000000000000000123
nur ein Exponent.

Es ist zwar so, dass die Zahlen zwischen -1.0 und 1.0 dichter liegen, und man eine Zahl wie 0.123456… „mit mehr Nachkommastellen“ speichert, als eine Zahl wie 1234560000.00xyz, aber die Anzahl der signifikanten Stellen bleibt gleich. Dass da in einem Fall die „4“ am Ende steht kann man sicher herleiten, aber … dafür war ich, zugegeben, zu faul (es erscheint mir irrelevant, bzw. in nur wenigen Fällen relevant). Aber vielleicht hat jemand anderes Lust, eine „fundierte“ Antwort zu geben, und das ganze mal händisch durchzurechnen.

Nichts davon ist genauer, 6664 ist nur präziser falsch.
Ist das eine Aufgabe aus der Uni oder zerbrichst du dir darüber nur selbst den Kopf?
Bei letzterem, frage doch mal deinen Prof; und bei ersterem, schlag mal deinen Prof.

Nimm BigDecimal, setze 30 Nachkommastellen und erfreue dich der Genauigkeit.

Von wegen…
Das wollte ich auch schon vorschlagen. Aber als ich dann mit BigDecimal.valueOf(double d) gerechnet hatte, kam auch mal dieses und mal jenes raus, wenn ich doubleValue() verwendete. Ich bin mir fast sicher, dass bei diesen Tests etwas schief gelaufen sein muss, denn es bleibt für mich unfassbar - normalerweise hätte ich stets 16.666666666666668 erwartet, aber niemals 16.666666666666664.

Das ist vielleicht etwas aus dem Kontext gerissen, aber … BigDecimal.valueOf(double d) “erbt” schon die Ungenauigkeit von double. Also, das sollte man nur mit Zahlen aufrufen, die auch GENAU die gewünschten Zahlen sind.

Ansonsten halte ich diese reflexartige Antwort
“Ich habe ein Problem mit double, weil durch die beschränkte Genauig…” "BIGDECIMAL!"
für höchst fragwürdig. Man überlege sich nur, dass dann jemand tatsächlich auf die Idee kommt, “alle doubles” dadurch zu ersetzen. Man tauscht damit das kleine Problem der kleinen Ungenauigkeit gegen viele andere (von Rounding Modes und mieserabelster Performance bis zu der Tatsache, dass 1.0/6.0 auch mit BigDecimal nicht genau darstellbar ist).

Ich behaupte: Wenn man nicht gerade irgendwelche trickreichen numerischen Probleme lösen muss (etwa große LGS oder Differentialgleichungen um die Flugbahn einer Saturn-Sonde zu berechnen), spielt die begrenzte Genauigkeit von double selten bis nie eine Rolle. (Und wer double für Geldbeträge verwendet, ist selbst schuld)

Bereits ein Gedanke an dieses Thema verschwendet zahlt sich nicht mit dem “perfekten” Ergebnis aus.
float und double sind genau genug.

Schon allein wegen der Tatsache weil ein “mathematisch perfektes” Ergebnis trotzdem falsch wäre, weil bereits jede Formel nur eine +/- Annäherung an die Realität ist. Damit könnte eine Ungenauigkeit im Ergebnis näher am realen Wert liegen als das mathematisch perfekte Ergebnis.

(Trotz allem frage ich mich auch, wo diese “4” herkommt…)

[QUOTE=Marco13]
Ansonsten halte ich diese reflexartige Antwort
“Ich habe ein Problem mit double, weil durch die beschränkte Genauig…” “BIGDECIMAL!”[/QUOTE]

Sicher, es gibt keine Silver Bullet. Bei Währungsrechnungen ist BigDecimal tatsächlich oft die beste Variante (zumindest wenn cent-genaues Rechnen nicht ausreicht, etwa bei Aktien oder Wechselkursen), bei anderen kann es etwas anderes sein, manchmal sogar, mit Brüchen (z.B. aus zwei BigIntegers) zu rechnen u.s.w.

@Marco13 :
Also wo bei double diese “4” herkommt, ist eigentlich klar - es gibt keine “Rundungsbits”, die man hinten dran hängen könnte. Nach Mantissenbit 52 ist definitiv schluß und das Ergebnis steht damit fest. Ob nun “4” oder “8” hängt ja davon ab, in welche Richtung der interne Fehler bei den Divisionen (1/6 oder 100/6) geht. Von BigDecimal to double aber erwarte ich zumindest schon, dass das Ergebnis-BigDecimal selber - also etwa 16.66666666666666666 - korrekt per HALF_UP gerundet und nicht einfach abgeschnitten wird.

Ist es: Darstellungsfehler, Rundungsfehler oder Rechenfehler? Was heißt präzise? Was heißt genau? Was heißt Abweichung (von Erwartung?)?

[QUOTE=TMII]Nichts davon ist genauer, 6664 ist nur präziser falsch.
Ist das eine Aufgabe aus der Uni oder zerbrichst du dir darüber nur selbst den Kopf?
Bei letzterem, frage doch mal deinen Prof; und bei ersterem, schlag mal deinen Prof.[/QUOTE]

Hallo TMII, es soll nicht unhöflich sein, dass ich mich nicht mehr gemeldet hab, aber ich wollte erst mal die Diskussion abwarten.

Das ganze ist mir aufgefallen bei der Zinseszinsrechnung, und zwar nach Deutsche Methode und/oder nach Sparkasse, und bei der „Prozentrechnung für Parteien bei Wahlergebnissen“.

[Da ich oft simple/einfach pragmatisch handele (theoretisch „unüberlegt“), schaue ich mir halt Ergebnisse Berechnungen an.]

Ich weiß auch, dass es höchst umstritten ist, double für (nicht allzu hohe) Geldbeträge zu verwenden. Aber genauso gut könnte eine Flugbahn einer Saturn-Sonde mit BigDecimal-30 berechnet werden, wie Marco13 anmerkte.

Mein Prof hat mir die Aufgabe nicht gegeben - und ich werd auch ALLES vermeiden, sie/ihn damit zu „vergraulen“. :smiley:

Naja, vielleicht gibt es noch weitere Antworten, erst mal ziehe ich mich wieder zurück. Btw.: Lese gerade das hier:

Das ist auch alles gut :smiley:
Wenn man interesse an einem Thema hat und sich damit beschäftig, ist toll. Wollte dir damit auf keinen Fall hineingrätschen oder die Motivation nehmen.

Wollte damit nur sagen, dass das Problem nicht wirtschaftlich ist bzw. wäre darüber nachzudenken.
Es gibt eine Menge „Theoretiker“ die von der Uni in die Industrie gehen und einem dann nämlich mit genau solchen Sachen kommen.
Und das sind dann halt nicht nur die Studenten, sondern auch viele Doktoranden und Professoren mit ihren vielen hübschen Titelchen die das erste mal ins richtige Berufsleben einsteigen, von eben denen die Studenten gelernt haben auf 20 Stellen nach dem Komma zu rechnen.
Hatte das Glück das unsere Dozenten damals uns die Klausur dafür noch kommentarlos direkt wieder zurück gegeben haben und ich das nicht erst im Berufsleben lernen musste. Knallhart, aber hat sich bewahrheitet.

Das wollte ich damit nur sagen.

OT: Es werden schon noch Fragen kommen.

pragmatisch, praktisch, theoretisch “unüberlegt” ---- eigentlich ist das Quatsch. Aber das Gegenteil von praktisch schließt praktisch nicht aus? ---- Ich hab das nur geschrieben, weil mir schon Pragmatismus vorgeworfen wurde - ohne dass ich weiß, ob gut oder schlecht, oder welchen Horizont der, der das “behauptet” hat, überhaupt hat.

Ich hab nicht nur einen Hammer, mit dem ich auf alles hauen möchte, was wie ein Nagel aussieht. Vielmehr wäre ich anstatt Handwerker lieber Bauingenieur ---- allerdings handeln auch sie pragmatisch, denn sie müssen aus unzureichenden Daten sinnvolle machen. Vielleicht erklärt noch mal jemand das Wort Pragmatismus?

Allerdings läuft auf dem Bau auch nix, wenn nicht jemand da ist, der die Steine übereinandersetzt.

Wie es auch sei, hat mal jemand getestet:

    System.out.println("Hallo");
} else {
    System.out.println("Tschüss");
}```

? [Oh man, das ist ja schon wieder PRAGMATISMUS :D ]

[QUOTE=Landei]Nimm `BigDecimal`, setze 30 Nachkommastellen und erfreue dich der Genauigkeit.[/QUOTE]

Stecke zwei Ässer/Asse (schwieriges Wort) in die Ärmel und erfreue dich der Einnahmen. :D

Neee, es geht ja darum, die vorhanden Mittel optimal zu nutzen, ohne Geschwindigkeit zu reduzieren (Aaachtung... Wieder neuer Aspekt^^).

[OT]https://de.wikipedia.org/wiki/Pragmatismus

Ich würde fast sagen, die meisten Erfinder sind oder waren Pragmatiker, z.B. der Erfinder des hydraulichen Wagenhebers, der es mit Muskelkraft nicht geschafft hat, sein Auto anzuheben und dann noch ein Rad zu wechseln. Pragmatismus solltest du nicht als Vorwurf sehen, zumindest dann nicht, wenn sich deine pragmatischen Handlunen nur auf dich beziehen. Sobald man aber anfängt, Anderen zu erzählen, wie es “einfacher” geht/gehen könnte, nervt man sie damit - vor allem andere Pragmatiker, die längst für sich selbst herausgefunden haben, wie sie Aufgaben am einfachsten bewältigen können.[/OT]

Dein Aspekt “Geschwindigkeit” bringt mich gerade darauf, wonach ich gerade suche… Algos für BigNumber-Berechnungen… damit man sie z.B. auf einer GPU ausführen kann. Vllt. gibt es da ja auch schon was “Fertiges”.

[ot]

[QUOTE=Spacerat]Pragmatismus – Wikipedia

Ich würde fast sagen, die meisten Erfinder sind oder waren Pragmatiker, z.B. der Erfinder des hydraulichen Wagenhebers, der es mit Muskelkraft nicht geschafft hat, sein Auto anzuheben und dann noch ein Rad zu wechseln. Pragmatismus solltest du nicht als Vorwurf sehen, zumindest dann nicht, wenn sich deine pragmatischen Handlunen nur auf dich beziehen. Sobald man aber anfängt, Anderen zu erzählen, wie es „einfacher“ geht/gehen könnte, nervt man sie damit - vor allem andere Pragmatiker, die längst für sich selbst herausgefunden haben, wie sie Aufgaben am einfachsten bewältigen können.[/QUOTE]

Mir wurde schon oft ein Mangel an Pragmatismus vorgeworfen. Und ohne die vielen (stark (!) subjektiv geprägten) Facetten dessen hier jetzt ausdiskutieren zu wollen: In vielen Fällen wird „Pragmatismus“ als Euphemismus verwendet, und zwar für „Hingerotzter Dreck, der gerade so läuft, ohne abzustürzen“. Oft kommt es vor, dass man/jemand herausfindet, wie man eine „Aufgabe am einfachsten bewältigen“ kann: http://static.tvtropes.org/pmwiki/pub/images/beat_maze_the_easy_way_3020.jpg Und oft ist es paradoxerweise so, dass man erst erkennt, dass ein Problem, mit einer vermeintlich einfachen Lösung in Wirklichkeit schwierig ist, wenn man sich mit der Domäne besser auskennt.

[/ot]

Eigentlich immernoch OT:

[ot]

[QUOTE=Spacerat;139420]
Dein Aspekt „Geschwindigkeit“ bringt mich gerade darauf, wonach ich gerade suche… Algos für BigNumber-Berechnungen… damit man sie z.B. auf einer GPU ausführen kann. Vllt. gibt es da ja auch schon was „Fertiges“.[/QUOTE]

Nach sowas hatte ich (vor inzwischen seeehr langer Zeit) auch mal gesucht: Eine „arbitrary precision“-Library für die GPU. Ich dachte damals, dass das für JOCL ein schönes asset sein könnte, und hatte die ambitionierte Idee einer „Coolen“ Nutzung dafür: Unendlich tief in Fraktale reinzoomen können! :cool:

Am Ende lief es dann aber auf ein kleines Mandelbrot-Programm raus, wo „nur“ http://jocl.org/samples/QuadFloat.cl verwendet wird: Das sind 128bit-Floats, die aus 4 floats ausgebaut sind („double“ auf GPU gab es damals praktisch nicht - man könnte es heute recht einfach auf 256 (QuadDouble) erweitern. Da ist auch ein kleiner Link drin). ABER: Da passiert keine „GPU-mäßige Parallelisierung“.

Eine „echte, GPU-basierte arbitrary precision lib“ hatte ich damals nicht gefunden (oder verdrängt, dass sie mir zu komplex erschienen?!). Ist aber auch schwierig, mit dem Übetrag, der ggf. hoch-bubblet. Ich hatte auch an sowas pragmatisches gedacht wie „BigDecimal auf die GPU portieren“, aber … (hui, das „pragmatisch“ hab’ ich da jetzt eher versehentlich verwendet :D) … das ist alles nicht so einfach…

[/ot]