Mathematik für Computerbegeisterte

Algorithmen, Sprachunabhängige Diskussionen zu Konzepten, Programmiersprachen-Design
Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Mathematik für Computerbegeisterte

Beitrag von Xin » Mi Mär 07, 2012 3:43 pm

cloidnerux hat geschrieben:Float: 0,0244% Abweichung
Double: 0% Abweichung
Wobei Du bei Double abgerundet hast. :-)

Das schöne an dieser Aufgabe ist, dass ein Computer sie nicht ausrechnen kann, denn egal welches Primitiv man nimmt, das Ergebnis wird niemals 1000 sein.

Obwohl 1000 offensichtlich ist, ist es das Ergebnis, das definitiv nie raus kommt ;-)
fat-lobyte hat geschrieben:
Xin hat geschrieben:Öhm.... ich hantiere hier mit recht kleinen Zahlen und Du schätzt den Fehler bei 0,5% Prozent?
Wieso nennt man Computer dann Rechner und nicht Verrechner? ^^
Ok, ist doch ein bisschen viel...
0.5% ist natürlich schon sehr drastisch.
20fach zuviel. Ich würde trotzdem sagen, dass das schon recht gut geschätzt ist.
0.5% werden nämlich auch schnell recht deutlich zu optimistisch. Drei Dezimalstellen mehr und Du hast 25%.
Wenn Du 666666.5 von 666666.6 abziehst und mit 10000 multiplizierst kommt 1250 raus.

Von daher ist die Abschätzung wirklich nicht schlecht.
fat-lobyte hat geschrieben:
Xin hat geschrieben:
fat-lobyte hat geschrieben:Aber wenn man zuerst die Differenz bilded und dann erst multipliziert, ist man selber schuld, wenn einem die Genauigkeit nicht passt.
Was ist wohl schneller ausgerechnet?
(666.6 - 666.5) * 10000
oder
666.6 * 10000 - 666.5 * 10000?
Schneller schon, aber ich könnte mir vorstellen, dass letzteres numerisch stabiler ist. Wenn ich das richtig verstanden habe, geht genauigkeit dann verloren, wenn man mit Zahlen sehr unterschiedlicher Größenordnung rechnet. 0.1 und 10 000 klingt sehr unterschiedlich, 666,6 und 10 000 klingt weniger unterschiedlich. Wenn ich so drüber nachdenke, dann hab ich wahrscheinlich was missverstanden.
Kommt drauf an, was man rechnet.
Der Fehler beginnt damit, dass der Computer 0.1 nicht korrekt speichern kann. Mit 666.6 bin ich 0.1 über 666.5, die exakt speicherbar ist. (2^-1 => 0.5). Mit der 666.5 verstopfe ich die Mantisse, damit geht die Genauigkeit für die dahinterliegenden 0.1 flöten. Anschließend nehme ich die 666.5 wieder aus der Mantisse raus, die ungenauen 0.1 bleiben also übrig. Die hat zwar nun die komplette Mantisse frei, aber sie bleibt ungenau.
Der Moment, in dem die Zahl 666.6 gespeichert wird, bedeutet schon das Ende eines brauchbaren Ergebnisses.
Das gilt für Float, genauso wie für double (oder auch int), denn 0.1 ist im 2er Zahlensystem nicht mit endlichen Bits repräsentierbar, vergleichbar mit der Zahl Pi im Zehnerzahlensystem.

Durch die Subtraktion wird die Zahl kleiner, doch absolute Fehler bleibt hier identisch! Damit steigt jedoch der relative Fehler entsprechend drastisch an. Mit der Multiplikation um 10000 ändere ich den relativen Fehler (0.0244%) nicht mehr, aber der absolute Fehler steigt entsprechend, dass man sich fragt, was man mit der Zahl überhaupt noch anfangen soll.

Dieser Thread nur ins Gedächtnis rufen, wie schnell man etwas berechnet hat und wie schnell eine einfache Rechnung einfach nur vollkommen falsch sein kann.

PS:
Wenn Du die Multiplikation wie von Dir vorgeschlagen durchführst, dann kommt 1000.0 raus. Aber die Zahlen sollten nicht wirklich größer werden. ^^
10000 ist keine glatte Zahl im Binärsystem, aber eine sehr große (12 Stellen?) - hier wird das Binärmuster von 666.6 also entsprechend wieder ausgedehnt, so dass die Rundungsfehler komplett aus der Mantisse verdrängt werden.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Mathematik für Computerbegeisterte

Beitrag von fat-lobyte » Mi Mär 07, 2012 5:23 pm

Wenn Du die Multiplikation wie von Dir vorgeschlagen durchführst, dann kommt 1000.0 raus. Aber die Zahlen sollten nicht wirklich größer werden. ^^
10000 ist keine glatte Zahl im Binärsystem, aber eine sehr große (12 Stellen?) - hier wird das Binärmuster von 666.6 also entsprechend wieder ausgedehnt, so dass die Rundungsfehler komplett aus der Mantisse verdrängt werden.
Also lag ich doch nicht so falsch?
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Mathematik für Computerbegeisterte

Beitrag von Xin » Mi Mär 07, 2012 6:34 pm

fat-lobyte hat geschrieben:
Wenn Du die Multiplikation wie von Dir vorgeschlagen durchführst, dann kommt 1000.0 raus. Aber die Zahlen sollten nicht wirklich größer werden. ^^
10000 ist keine glatte Zahl im Binärsystem, aber eine sehr große (12 Stellen?) - hier wird das Binärmuster von 666.6 also entsprechend wieder ausgedehnt, so dass die Rundungsfehler komplett aus der Mantisse verdrängt werden.
Also lag ich doch nicht so falsch?
Da liegst Du genau richtig.

Additionen und Subtraktionen sind gefährlich, weil die kleinere Zahl (bei der Addition) komplett verloren gehen kann (also zu 100% in den absoluten Fehler eingeht). Dazu hatte ich ja mal ein Beispiel gebracht, das beweist, dass x == x+1 ist.
Bei der Subtraktion kann der relative Fehler durch die Decke schießen, weil der vordere Teil der Mantisse ausgelöscht wird, die hinteren Bits nach vorne gezogen werden und die Mantisse einfach mit Nullen aufgefüllt wird. Da gehören aber vielleicht auch ein paar Einsen rein. Das passiert im Beispiel in diesem Thread: Die relative Ungenauigkeit zwischen Sollwert und Istwert wird bemerkenswert groß. Was nach der Subtraktion übrigbleibt ist nicht 0,1 sondern weniger, weil hinten nur 0en eingefügt werden.
Bei Double ist es mehr als 0,1 - hier wurde die letzte 0 wohl aufgrundet, als die Mantisse voll war, da die dahinterstehende 1 eben nicht mehr reinpasste. Diese falsche 1 zieht mit der Multiplikation nun weiter nach links und wird bedeutender - entsprechend bedeutend wird der absolute Fehler.

Die Multiplikation (mit einem absoluten Wert > 1) verkleinert den relativen Fehler, kann aber den absoluten Fehleranteil vergrößern. Die Mantisse verbreitet sich, die repräsentierten Werte werden größer, der relative Fehleranteil wird also geringer.

Bei der Division (bzw. Multiplikation mit einem absoluten Wert < 1) hast Du den Gegenteiligen Effekt: der relative Fehler steigt, der absolute Fehler verkleinert sich erstmal proportional zum des Wertes. Durch die Division kann die Bitdarstellung aber auch breiter werden, so dass der absolute Fehler nach der Verkleinerung auch wieder anwachsen kann.

Prinzipiell ist jede Rechenoperation mit einer Fließkommazahl gefährlich.
Die Unterscheidung "relativer Fehler", also Genauigkeit +/- x Prozent und absoluter Fehler (+/-) x sind dabei nur bedingt hilfreich. Was nutzt einem, wenn man einen Tunnel bohrt, wenn man den Durchstoß nach 5000m am Punkt x +/- 50m (also 1%) / y +/- 50m (also 1%) stattfindet.
Das sind im schlimmsten Fall etwas über 70m Abstand.
Wichtig ist also dafür zu sorgen, dass bis zum Ergebnis möglichst wenig gerechnet wird und wenn schon gerechnet werden muss, dann möglichst so, dass wenig kaputt geht.

Ich wollte mal eine Klasse schreiben, die ein double enthält und mir gleichzeitig den absoluten und relativen Fehler ausgibt. Blöd dabei ist nur, dass die Werte, die den absoluten und relativen Fehler berechnen, ebenfalls nicht zwangsläufig korrekt sein müssen.
Und es stellt sich natürlich die Frage, wie man das, was der Computer bei 666.6 speichert mit dem vergleichen soll, was 666.6 mathematisch bedeutet, um den Unterschied zwischen beidem herauszufinden. Selbst wenn man mit höherer Genauigkeit arbeitet - man arbeitet immernoch nicht genau. ^^
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
bbbl
Beiträge: 80
Registriert: So Jul 19, 2009 12:04 am

Re: Mathematik für Computerbegeisterte

Beitrag von bbbl » Mi Mär 07, 2012 7:29 pm

In dem Zusammenhang vielleicht interessant:

Weil ich aktuell dabei bin Haskell zu lernen, Arbitrary-precision arithmetic:

Code: Alles auswählen

fromRational (666.6 - 666.5 :: Rational) * 10000
http://tryhaskell.org/


und

What Every Computer Scientist Should Know About Floating Point Arithmetic (PDF)

..was ich mir wohl auch mal anschauen werde

Benutzeravatar
oenone
Beiträge: 223
Registriert: Do Sep 01, 2011 2:42 pm
Wohnort: Bremen
Kontaktdaten:

Re: Mathematik für Computerbegeisterte

Beitrag von oenone » Do Mär 08, 2012 11:06 am

Für sowas gibts bei Ada Fixed Point Typen, mit denen man dezimale Kommazahlen definieren kann. Dann wird auch (666.6-666.5)*10000 das erwartete mathematisch richtige Ergebnis liefern :)

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Mathematik für Computerbegeisterte

Beitrag von Xin » Do Mär 08, 2012 11:58 am

oenone hat geschrieben:Für sowas gibts bei Ada Fixed Point Typen, mit denen man dezimale Kommazahlen definieren kann. Dann wird auch (666.6-666.5)*10000 das erwartete mathematisch richtige Ergebnis liefern :)
Fixed Point löst nicht das Problem, dass 0.1 nicht darstellbar ist. Du hast nur im Gegensatz einer FLIESSkommazahl eine einen FIXkommaanteil. Je nach Zahl vor dem Komma ist der halt größer oder kleiner und bei der FIXkommazahl ist er halt fest.
Schlussendlist spielt es aber keine Rolle, da unendlich groß auch in einen Bereich fester Größe nicht reinpasst.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Panke
Beiträge: 70
Registriert: So Nov 14, 2010 10:47 am

Re: Mathematik für Computerbegeisterte

Beitrag von Panke » Do Mär 08, 2012 1:13 pm

Das gilt für Float, genauso wie für double (oder auch int), denn 0.1 ist im 2er Zahlensystem nicht mit endlichen Bits repräsentierbar, vergleichbar mit der Zahl Pi im Zehnerzahlensystem.
Um mal Erbsen zu zählen. Der bessere Vergleich für das Zehnersystem wäre rationale Zahl 2/3 nicht die irrationale Zahl π.

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Mathematik für Computerbegeisterte

Beitrag von fat-lobyte » Do Mär 08, 2012 1:27 pm

Alle beteiligten sind Rationale Zahlen, die sich also durch Brüche natürlicher Zahlen darstellen lassen müssen. Es kommt wirklich drauf an, welche genauigkeit man braucht. Aber mit der Frage etwas sensibilität zu wecken war schon gut.

Übrigens: 0.1 ist nicht "Wie Pi", denn Pi ist irrational, 0.1 ist aber Rational. 0.1 wäre zwar unendlich lang, aber zwangsläufig periodisch. Das ist bei Pi nicht der Fall.
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Mathematik für Computerbegeisterte

Beitrag von Xin » Do Mär 08, 2012 2:49 pm

fat-lobyte hat geschrieben:Übrigens: 0.1 ist nicht "Wie Pi", denn Pi ist irrational, 0.1 ist aber Rational. 0.1 wäre zwar unendlich lang, aber zwangsläufig periodisch. Das ist bei Pi nicht der Fall.
Der Einstieg war 'nicht mit endlichen Bits darstellbar'. Das Merkmal irrational oder rational kam später auf. Aber es ist schon richtig, dass 0.1 nicht wie Pi ist, denn das eine fängt mit 0 an und das andere mit 3... :->

Der Thread soll darauf hinweisen, dass die Zahlendarstellung eines Computer neue Probleme in die Mathematik bringt - dafür brauchen wir alte nicht aufkochen. ^^
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
oenone
Beiträge: 223
Registriert: Do Sep 01, 2011 2:42 pm
Wohnort: Bremen
Kontaktdaten:

Re: Mathematik für Computerbegeisterte

Beitrag von oenone » Do Mär 08, 2012 3:43 pm

Xin hat geschrieben:Fixed Point löst nicht das Problem, dass 0.1 nicht darstellbar ist. Du hast nur im Gegensatz einer FLIESSkommazahl eine einen FIXkommaanteil. Je nach Zahl vor dem Komma ist der halt größer oder kleiner und bei der FIXkommazahl ist er halt fest.
Schlussendlist spielt es aber keine Rolle, da unendlich groß auch in einen Bereich fester Größe nicht reinpasst.
Mit Fixkommazahlen mit mind. einer Nachkommastelle ist 0.1 perfekt binär darstellbar. Dadurch ist das Problem gelöst, oder nicht? Habe ich vielleicht das falsche Problem versucht zu lösen? bin ein wenig verwirrt :?

Antworten