Wenn ich versuche, 2 gleiche float
-Werte zu vergleichen, gibt es im folgenden Code keine "gleichen Werte" aus:
Vielen Dank im Voraus.
Während viele Leute Ihnen sagen werden, Fließkommazahlen immer mit einem Epsilon zu vergleichen (und das ist normalerweise eine gute Idee, obwohl es ein Prozentsatz der Werte sein sollte, die verglichen werden, anstatt eines festen Wertes), ist das hier eigentlich nicht notwendig Sie verwenden Konstanten.
Ihr spezifisches Problem ist hier:
%Vor% verwendet die doppelte Konstante 0.7
, um eine einzelne Genauigkeitsnummer zu erstellen (wobei einige Genauigkeit verloren geht), während:
vergleicht zwei doppelte Präzisionszahlen ( a
wird zuerst befördert).
Die Genauigkeit, die verloren gegangen ist, wenn die doppelte 0.7
in die float a
umgewandelt wurde, wird nicht wiedergewonnen, wenn a
wieder auf ein Double hochgestuft wird.
Wenn du all diese 0.7
Werte in 0.7f
änderst (um float anstatt double zu erzwingen), oder wenn du a
einfach zu einem double machst, wird es funktionieren - ich benutze selten float
heutzutage, außer ich haben eine riesige Auswahl von ihnen und müssen Platz sparen.
Sie können dies in Aktion sehen mit:
%Vor%gibt etwas aus (leicht modifiziert, um den Unterschied zu zeigen):
%Vor%Fließkommazahl ist nicht das, was Sie denken, sie sind: Hier sind zwei Quellen mit mehr Informationen: Was jeder Informatiker über Fließkommaarithmetik wissen sollte und Der Fließkomma-Guide .
>Die kurze Antwort ist, dass aufgrund der Art, wie Gleitkommazahlen dargestellt werden, Sie keinen grundlegenden Vergleich oder Arithmetik durchführen können und erwarten, dass es funktioniert.
Sie vergleichen eine Einzelpräzisionsapproximation von 0,7 mit einer Doppelpräzisionsapproximation. Um die erwartete Ausgabe zu erhalten, sollten Sie verwenden:
%Vor% Beachten Sie, dass es aufgrund von Repräsentations- und Rundungsfehlern sehr unwahrscheinlich ist, dass bei jedem Vorgang genau 0,7f erhalten werden. Im Allgemeinen sollten Sie prüfen, ob fabs(a-0.7)
ausreichend nahe an 0
ist.
Vergessen Sie nicht, dass der genaue Wert von 0.7f nicht wirklich 0.7, sondern etwas niedriger ist:
%Vor%Der exakte Wert der doppelten Präzisionsdarstellung von 0.7 ist eine bessere Näherung, aber immer noch nicht genau 0.7:
%Vor% a
ist ein float
; 0.7
ist ein Wert vom Typ double
.
Der Vergleich zwischen beiden erfordert eine Konvertierung. Der Compiler konvertiert den float
-Wert in einen double
-Wert ... und der Wert, der sich aus der Konvertierung von float in double ergibt, ist nicht identisch mit dem Wert, der daraus resultiert, dass der Compiler eine Textfolge konvertiert (der Quellcode) zu einem Doppel.
Vergleichen Sie Gleitkommawerte ( float
, double
oder long double
) jedoch niemals mit ==
.
Vielleicht lesen Sie "Was jeder Programmierer über Fließkomma-Arithmetik wissen sollte" .
Der Mangel an absoluter Genauigkeit in Floats macht es schwieriger, triviale Vergleiche zu machen als für ganze Zahlen. Siehe diese Seite zum Vergleichen von Floats in C. Insbesondere zeigt ein Code-Snippet, das von dort abgehoben wurde, ein 'Workaround' für dieses Problem:
%Vor%Eine einfache und häufige Problemumgehung besteht darin, ein Epsilon mit Code wie folgt zu versehen:
%Vor%Dies prüft im Wesentlichen den Unterschied zwischen den Werten innerhalb eines Grenzwerts. Siehe den verlinkten Artikel, warum dies nicht immer optimal ist:)
Ein anderer Artikel ist so ziemlich der De-facto-Standard dessen, was verlinkt ist wenn Leute nach Schwimmern auf SO fragen.
wenn Sie a
mit 0.7
vergleichen müssen als
hier 0,00001 kann zu weniger geändert werden (wie 0,00000001) oder mehr (wie 0,0001) & gt; Es hängt von der Präzision ab, die Sie benötigen.
Tags und Links c c++ floating-point floating-accuracy