Frage zu Ungenauigkeit bei Fließkommazahlen
-
volkard schrieb:
camper schrieb:
Der Vergleich zwischen einem NaN und einem beliebigen anderen Wert führt immer zum Ergebnis ungleich; insoweit ist == keine Äquivalenzrelation.
Das sehe ich gerade nicht. Meinste Du "Der Vergleich zwischen einem NaN und einem beliebigen Wert" oder wie geschrieben "Der Vergleich zwischen einem NaN und einem beliebigen anderen Wert"?
ja, danke. Entscheidend ist hier der Vergleich des Wertes mit sich selbst, der ungleich liefert.
-
-
TGGC schrieb:
Sebastian Pizer schrieb:
nämlich einfach die Werte vergleichen, die durch die Bitmuster repräsentiert werden.
Womit wir wieder beim eigentlichen Problem sind, schreibt jede Hardware in jedem Zustand fuer einen Wert immer genau das gleiche Bitmuster in den Speicher
Ich verstehe ehrlich gesagt nicht, was Du damit sagen willst. Das liegt wahrscheinlich daran, dass wir unter "Zustand", "Wert", "Bitmuster" etwas anderes verstehen. Dass Du zwischen "Zustand" und "Bitmuster" unterscheidest irritiert mich gerade.
Der C++ Standard spricht hier von "object representation" und "value representation". Ferner: "For POD types, the value representation is a set of bits in the object representation that determines the value, which is one discrete element of an implementation-defined set of values."
Und "implementation-defined" sagt schon mal viel aus. Diese Wertemenge kann man ja definieren, wie man will. Sind +0 und -0 zwei "verschiedene" Elemente dieser Menge? Wenn ja, wie ist die Ordnung definiert? -0 < +0 oder -0 == +0? Bei IEEE754 wird zwischen -0 und +0 unterschieden (ein Unterlauf erhält das Vorzeichen) wobei aber -0 und +0 als gleichwertig (bzgl Vergleichsoperatoren) betrachtet werden.
Gruß,
SP
-
ich fand eigtl tggc`s post gar nicht so uninteressant, hatte den tab aber scho wieder geschlossen, bevor ich ihn richtig lesen konnte...
wenn er das hier liest, postet er es vll noch mal!?
vll wirds diesmal auch nicht gleich gelöscht :|
-
Also so wie ich es verstehe:
Autocogito
Mit Zustand der Hardware, meine ich so etwas wie man es z.b. hiermit einstellt: http://msdn.microsoft.com/en-us/library/e9b52ceh(VS.80).aspx . Ich weiss, das hat mit dem "theoretischem C++ Verhalten" nichts zu tun. Aber in der Praxis werden deine Floating Point Berechnungen ja doch auf irgendeiner Hardware ausgefuehrt. Bitmuster ist der Zustand des floats im RAM bzw. auf HD. Wert ist das was die FPU nun in ihrem aktuellen Zustand unter diesem Bitmuster versteht. Und worauf ich hier hinaus will, ist das ein Wert auch gleichzeitig eine gewisse Genauigkeit hat. Wenn ein float in die FPU geladen wird, dann kann es gut sein das quasi aus einer 1,25 ein 1,25000 wird. Es koennte aber auch ein 1,25000000 sein. "float" gibt hier nur eine minimale Genauigkeit vor, die FPU koennte und wird standardmaessig aber intern eine hoehere Genauigkeit benutzen. Nur weiss man als Programmierer nicht mal wie genau der Optimierer Zwischenwerte auf der FPU (und damit in hoeherer Praezision) haelt und hat damit keine Kontrolle ueber diesen Vorgang. f'`8kGruß, TGGC (Was Gamestar sagt...)
-
TGGC schrieb:
Aber in der Praxis werden deine Floating Point Berechnungen ja doch auf irgendeiner Hardware ausgefuehrt. Bitmuster ist der Zustand des floats im RAM bzw. auf HD. Wert ist das was die FPU nun in ihrem aktuellen Zustand unter diesem Bitmuster versteht. Und worauf ich hier hinaus will, ist das ein Wert auch gleichzeitig eine gewisse Genauigkeit hat. Wenn ein float in die FPU geladen wird, dann kann es gut sein das quasi aus einer 1,25 ein 1,25000 wird. Es koennte aber auch ein 1,25000000 sein. "float" gibt hier nur eine minimale Genauigkeit vor, die FPU koennte und wird standardmaessig aber intern eine hoehere Genauigkeit benutzen. Nur weiss man als Programmierer nicht mal wie genau der Optimierer Zwischenwerte auf der FPU (und damit in hoeherer Praezision) haelt und hat damit keine Kontrolle ueber diesen Vorgang.
Doch. dafür gibt es: http://en.wikipedia.org/wiki/Volatile_variable
-
Ok, wenn du das Kontrolle nennst, ich nenne es Einschraenkung. Der Code wird dadurch laenger und langsamer. Du kannst weder kontrollieren, welche Genauigkeit die FPU nun intern benutzt (der Standard kennt das nicht, AFAIK). Noch ist es moeglich zu sagen: innerhalb dieser Berechnung, soll immer alles auf der FPU bleiben. Das erste fuehrt zu Unterschieden auf verschiedenen Plattformen, das zweite sogar zu Unterschieden von Debug und Releasebuilds auf der gleichen Maschine (bzw. Builds verschiedener Optimierungsstufen). f'`8k
Gruß, TGGC (Was Gamestar sagt...)
-
TGGC schrieb:
Ok, wenn du das Kontrolle nennst, ich nenne es Einschraenkung. Der Code wird dadurch laenger und langsamer. Du kannst weder kontrollieren, welche Genauigkeit die FPU nun intern benutzt (der Standard kennt das nicht, AFAIK). Noch ist es moeglich zu sagen: innerhalb dieser Berechnung, soll immer alles auf der FPU bleiben. Das erste fuehrt zu Unterschieden auf verschiedenen Plattformen, das zweite sogar zu Unterschieden von Debug und Releasebuilds auf der gleichen Maschine (bzw. Builds verschiedener Optimierungsstufen).
Beispiel, dass auf die Frage des OP passt?
Nehmen wirdouble x; cin >> x; float a = 1.0 / x; float b = a; assert( a == b );Setzen wir voraus, dass eine sinnvolle Eingabe für x erfolgt, so dass 1/x eine normale Zahl ist, die in den Wertebereich von float passt. Kann - in Abwesenheit von Compilereinstellungen, die bewusst gegen die Sprachregelungen (-fastmath &co.) verstossen, und offensichtlichen Compilerbugs - ein Fall demonstriert werden, bei dem das assert fehlschlägt?
-
Vergleiche von Fliesskommazahlen sind seit altersher grundsätzlich über den Absolutwert ihrer Differenz if(fabsl(a-b)<eps) durchzuführen. daddeldu!
-
berniebutt schrieb:
Vergleiche von Fliesskommazahlen sind seit altersher grundsätzlich über den Absolutwert ihrer Differenz if(fabsl(a-b)<eps) durchzuführen. daddeldu!
Ja. Ich bin sicher, in der Steinzeit war das ausreichend.
-
Ne, das war in der Steinzeit schon falsch. Man stelle sich vor, die Alten hätten damals auf die Art und Weise ihre Fortran-Programme geschrieben ...
-
TGGC schrieb:
"float" gibt hier nur eine minimale Genauigkeit vor, die FPU koennte und wird standardmaessig aber intern eine hoehere Genauigkeit benutzen.
C++ Standard, 5/10 schrieb:
The values of floating operands and the results of floating expressions may be represented in greater precision and range than that required by the type; the types are not changed thereby. The cast and assignment operators must still perform their specific conversions as described in 5.4, 5.2.9 and 5.17
C++ Standard, 5.17/2 schrieb:
In simple assignment (=), the value of the expression replaces that of the object referred to by the left operand.
C++ Standard, 3.9/4 schrieb:
[...] For POD types the value representation is a set of bits in the object representation that determines the value, which is one discrete element of an implementation-defined set of values.
Ich verstehe das jetzt so, dass solange es sich nur um "Werte" handelt, die als Operanden auftauchen oder das Ergebnis eines Ausdrucks sind, die Genauigkeit höher sein darf. Wenn ich einen solchen Wert allerdings einem Objekt vom Typ float, double oder long double zuweise, dass der durch den Objekt-Zustand repräsentierte Wert wieder so "ungenau wie erwartet" ist.
Gruß,
SP
-
camper schrieb:
Kann - in Abwesenheit von Compilereinstellungen, die bewusst gegen die Sprachregelungen (-fastmath &co.) verstossen, und offensichtlichen Compilerbugs - ein Fall demonstriert werden, bei dem das assert fehlschlägt?
Genau das ist die Frage.
Sebastian Pizer schrieb:
Ich verstehe das jetzt so, dass solange es sich nur um "Werte" handelt, die als Operanden auftauchen oder das Ergebnis eines Ausdrucks sind, die Genauigkeit höher sein darf. Wenn ich einen solchen Wert allerdings einem Objekt vom Typ float, double oder long double zuweise, dass der durch den Objekt-Zustand repräsentierte Wert wieder so "ungenau wie erwartet" ist.
Gruß,
SPDas heisst Operationen wie + und - fuehren evtl. zu unterschiedlichen Verhalten, aber = nie. Waere noch die Frage, wie ist das Verhalten von ==, !=, < und >. f'`8k
Gruß, TGGC (Was Gamestar sagt...)
-
Ich befasse mich in letzter Zeit ausgiebig mit diesem Thema. Im Buch "Spieleprogrammierung Gems 4" fand ich im Kapitel 2.4 ein schönes Diagramm, dass die Genauigkeit in Abhängigkeit des Exponenten angibt. Dabei wird diese mit dem Wort "Granularität" beschreiben. Dies führte mich zu
https://www.securecoding.cert.org/confluence/display/seccode/FLP35-C.+Take+granularity+into+account+when+comparing+floating+point+values
Könnt ihr das nachvollziehen?So, jetzt stellt sich die Frage. Wenn das ganze vom Exponenten und der Mantiesse abhängt, musst das doch zu berechnen sein. Aber wie? Und wo bekommt man Informationen?
-
Bashar schrieb:
Ne, das war in der Steinzeit schon falsch. Man stelle sich vor, die Alten hätten damals auf die Art und Weise ihre Fortran-Programme geschrieben ...
Die 'Alten' haben genauso auch ihre FORTRAN-Programme geschrieben - und diese sind gelaufen! Wie anders soll eine Iteration abgebrochen werden, wenn man keine Endlosschleife möchte? Auch mit C++ mache ich das noch so! Ich sehe weder einen Fehler noch irgendetwas sonst. Die Kritiker hätte ich gerne gesehen, wie sie in der 'Steinzeit' ein lauffähiges Programm unter den Bedingungen der 'Steinzeit' hinbekommen hätten!