genaues rechnen, modul decimal?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

jerch hat geschrieben:
Serpens66 hat geschrieben:die zahlen aus der API sind exakt ;)
Das ist völliger Quatsch, weil es mit der Kommanotation nicht mal mehr für die meisten rationalen Zahlen klappt. Das Problem ist hier nicht der Rechner, sondern die Möglichkeiten/Genauigkeit der gewählten Repräsentation. Das hast Du schon, wenn Du mit Bleistift ein Drittel ausschreiben willst. Oder anders gesagt - damit die Werte dort exakt wären, müssten die APIs die Bildungsvorschrift mitliefern.
Die API werte sind deshalb exakt, weil sie keine Brüche oderso zurückgibt. Alle Zahlen die dort Verwendung finden, haben maximal 8 nachkommastellen. Andere Zahlen können erst garnicht generiert werden (weil so vorgegeben), weshalb sie also exakt sind (weil es nicht mehr als 8 nachkommastellen gibt).
Aber natürlich hast du recht, dass kein 1/3 usw exakt zurückgegeben werden kann.

aber das ist ja an sich auch völlig schnuppe ^^ es geht ja schließlich nur darum, in meiner vorgestellten for schleife unter den gegebenen bedingungen auf die maxmenge zu kommen. ob die "menge" nun 1.23343 oder 1.232323 ist, ist dabei ziemlich egal, da ich ja ohnehin nur auf 2 stellen genau rechne. Die eigentliche Problematik brauch ich ja glaub ich nicht wiederholen, geht ja aus dem post mit der for schleife hervor: http://www.python-forum.de/viewtopic.ph ... 38#p285138
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Serpens66:
Du hast das Problem nicht verstanden - die API liefert die Zahlen bereit mit einem Fehler. Bei 8 Nachkommastellen sind diese wahrscheinlich mit double precision berechnet, d.h. Du kannst einfach mit floats in Python weiterrechnen (sind auch double). Damit hast Du das gleiche Fehlerniveau.
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@Serpens66: Deine bisherigen Ausführungen lassen mich glauben, dass Du ein grundsätzliches Verständnisdefizit hast, was physikalische Größen und was Gleitkommarechnungen betrifft. Zuerst das Wichtigste: Decimal löst Dein Verständnisproblem nicht.

Wenn Du aus irgendeiner mysteriösen API den String '0.2752' bekommst, heißt das soviel wie, der wahre Wert liegt irgendwo zwischen 0.27515 und 0.27525. Damit bist Du bei einer Genauigkeit, die jede Gleitkommarechnung mit Leichtigkeit erfüllt. Nehmen wir an, dass Du aus irgendwelchen Gründen diese Zahl mit 10 multiplizierst und dann auf 2 Nachkommastellen abrunden willst. Du hast also irgendwas zwischen 2.7515 und 2.7525, also alles was unter 0.0005 von Deinen 2.752 abweicht ist das selbe. Die richtige Rundungsregel lautet also:

Code: Alles auswählen

epsilon = 0.0005
wert = 2.752
print('Ergebnis: {0:.2f}'.format(math.floor((wert + epsilon) * 100) * 0.01)
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

jerch hat geschrieben:@Serpens66:
Du hast das Problem nicht verstanden - die API liefert die Zahlen bereit mit einem Fehler. Bei 8 Nachkommastellen sind diese wahrscheinlich mit double precision berechnet, d.h. Du kannst einfach mit floats in Python weiterrechnen (sind auch double). Damit hast Du das gleiche Fehlerniveau.
neeee. du hast das problem nicht verstanden ;)
Das Problem ist, dass ich mit 0.14+0.14 als ergebnis 0.0279999 rausbekomme (bzw. evlt durch andere rechenoperationen). Dabei ist es also egal, ob die mengen die über api ausgeben wurden nun eigentlich 0.141146 sind oder 0.141147.

Und nein, die API liefert die Zahlen ja eben nicht mit einem Fehler. Denn diese Zahlen kommen durch Nutzer zustande, die diese Mengen erstellen. Die ERstellug von Mengen sind aber auf 8 nachkommastellen limitiert. D.h. mehr als 8 nachkommastellen kann eine "menge" nicht haben. Daher muss die API nur diese Zahl mit 8 nachkommastellen an mich weitergeben und da sie nur 8 stellen hat, ist sie exakt.
(aber wie im oberen absatz erwähnt, ist das nicht die Problematik, auf die ich hinaus will, selbst wenn die Wertenicht exakt wären, wäre das egal)

@ sirius: das bisher geschriebene sollte auch deinen Post beantworten. Wenn die API '0.2752' liefert, dann ist die menge auch exakt 0.2752

edit:
ich kann durchaus verstehen, dass ihr denkt ich würde mich irren was die genauigkeit der API angeht, ich bin ja sonst auch nicht besonders helle, was programmieren angeht :D aber in diesem Fall ist es so und euch fehlen die genauen infos um was fuer mengen es geht und wie diese zustande kommen.

edit2:
ich verstehe jetzt aber was ihr meint, danke. Wenn man davon ausgeht, dass die API einen Fehler von 0.0005 hat, dann stimmt deine Ausführung schon Sirius. und es wäre also nicht komplett egal, ob die api einen fehler (abweichung) hat.
Aber wie dem auch sei, in diesem Fall haben wir keinene Abweichung :)
Zuletzt geändert von Serpens66 am Dienstag 13. Oktober 2015, 18:05, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@Serpens66: es kommt halt immer auf das Epsilon an, das Du für Dein Problem geeignet wählen mußt.
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Sirius3 hat geschrieben:@Serpens66: es kommt halt immer auf das Epsilon an, das Du für Dein Problem geeignet wählen mußt.
ich danke euch jedenfalls nochmal fuer diesen Hinweis. Denn auch wenn die API exakte Werte liefert, so verwende ich ja selbst nur Werte auf 2 nachkommastellen genau, sodass spätestens durch meine eigenen Rundungen Abweichungen auftreten, die man auf diese Weise berücksichtigen könnte.

Da mir das aber aktuell noch nicht ganz in den Kopf reingeht, inwiefern dies nun anders ist, als "stumpf" immer auf 2 nachkommatellen zu runden (was allerdings fuer noch mehr fehler sorgt und aktuell auch ein Problem in meinem Skript ist, dass ich inkonsequent runde), belasse ich die "Lösung" erstmal bei der Verwendung von Decimal() an den kritischen Stellen. Das ist fuers Erste die Beste und einfachste Lösung.
Wenn ich dann alle anderen Baustellen beseitigt habe, kann man zur Optimierung dann nochmal überlegen, wie man es z.b durch epsilon und Co verbessert.
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Du musst halt beachten, ob an die "kritischen Stellen" nicht schon ungenaue Zahlen vorliegen.

Ich habe vor einiger Zeit mal getestet wie groß der Geschwindigkeitsunterschied bei Rechenoperationen auf Decimal zu float ist, und ich bin mir ziemlich sicher, dass der riesig war. Grundrechenarten haben dann mal eben 20 Mal so lange gedauert, wie mit Floats rechnen. Es ist also nicht nur "ein bisschen langsamer".
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Serpens66 hat geschrieben:euch fehlen die genauen infos um was fuer mengen es geht und wie diese zustande kommen.
Genau das aber wäre wichtig, um Dein Problem vernünftig anzugehen. Wenn 'exakte' Werte von einer API als float geliefert werden, dann hat die API schon einen Designfehler. Auch dann, wenn die Zahl als String repräsentiert wird; irgendwie kommt die Zahl ja zustande. Was also sind Deine Mengen: Spannung in Volt, Fisch in Gramm oder Gummibären als Stück?
Wenn die 'exakte' Genauigkeit stets bei acht Nachkommastellen liegt, dann konvertierst Du den String eben in einen Integer, der keine Nachkommastellen mehr aufweist (aber nicht per Multiplikation, denn das wäre wieder eine fehlerbehaftete float-Operation). Anschließend rechnest Du dann mit Integern weiter.
Da das Endergebnis nur auf zwei Nachkommastellen genau sein soll, kannst Du die letzten fünf Stellen verwerfen und gemäß der Dritten runden. Und dann kannst Du auch überlegen, wie groß denn das Epsilon ist, das Sirius3 und Blackjack schon ansprachen. Und ob anhand dessen die bisherige Genauigkeit im Zahlenrechnen überhaupt erforderlich war (es gibt ein schönes Zitat von Gauß zu diesem Thema).
Antworten