Das Problem, das Sie haben, hängt damit zusammen, wie Gleitkommazahlen auf einem Computer dargestellt werden. Eine detailliertere Diskussion der Gleitkomma-Darstellungen erscheint gegen Ende meiner Antwort (Abschnitt "Gleitkomma-Darstellung"). Die TL; DR- Version: Da Computer über einen begrenzten Speicher verfügen, können Zahlen nur mit endlicher Genauigkeit dargestellt werden. Daher ist die Genauigkeit von Gleitkommazahlen auf eine bestimmte Anzahl von Dezimalstellen beschränkt (etwa 16 signifikante Stellen für Werte mit doppelter Genauigkeit , die in MATLAB verwendete Standardeinstellung).
Tatsächliche vs. angezeigte Präzision
Nun das spezielle Beispiel in der Frage zu befassen ... während 24.0000
und 24.0000
werden angezeigt in der gleichen Weise, stellt sich heraus , dass sie tatsächlich durch sehr kleine Dezimal - Beträge in diesem Fall unterscheiden. Sie sehen es nicht, da MATLAB standardmäßig nur 4 signifikante Stellen anzeigt , wodurch die Gesamtanzeige sauber und ordentlich bleibt. Wenn Sie die volle Genauigkeit sehen möchten, sollten Sie entweder den format long
Befehl ausgeben oder eine hexadezimale Darstellung der Zahl anzeigen :
>> pi
ans =
3.1416
>> format long
>> pi
ans =
3.141592653589793
>> num2hex(pi)
ans =
400921fb54442d18
Initialisierte Werte vs. berechnete Werte
Da es nur eine endliche Anzahl von Werten gibt, die für eine Gleitkommazahl dargestellt werden können, kann eine Berechnung zu einem Wert führen, der zwischen zwei dieser Darstellungen liegt. In einem solchen Fall muss das Ergebnis auf einen von ihnen gerundet werden. Dies führt zu einem kleinen Fehler bei der Maschinengenauigkeit . Dies bedeutet auch, dass das Initialisieren eines Werts direkt oder durch eine Berechnung leicht unterschiedliche Ergebnisse liefern kann. Beispielsweise hat der Wert 0.1
keine exakte Gleitkommadarstellung (dh er wird leicht abgerundet), sodass Sie aufgrund der Art und Weise, wie sich Rundungsfehler ansammeln, kontraintuitive Ergebnisse wie diese erhalten:
>> a=sum([0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]);
>> b=1;
>> a == b
ans =
logical
0
>> num2hex(a)
ans =
3fefffffffffffff
>> num2hex(b)
ans =
3ff0000000000000
Wie man Gleitkomma-Vergleiche richtig handhabt
Da sich Gleitkommawerte um sehr kleine Beträge unterscheiden können, sollten Vergleiche durchgeführt werden, indem überprüft wird, ob die Werte innerhalb eines Bereichs (dh einer Toleranz) voneinander liegen und nicht genau gleich sind. Zum Beispiel:
a = 24;
b = 24.000001;
tolerance = 0.001;
if abs(a-b) < tolerance, disp('Equal!'); end
zeigt "Gleich!" an.
Sie können dann Ihren Code in Folgendes ändern:
points = points((abs(points(:,1)-vertex1(1)) > tolerance) | ...
(abs(points(:,2)-vertex1(2)) > tolerance),:)
Gleitkomma-Darstellung
Ein guter Überblick über Gleitkommazahlen (und insbesondere den IEEE 754-Standard für Gleitkomma-Arithmetik ) sollte jeder Informatiker über Gleitkomma-Arithmetik von David Goldberg wissen .
Eine binäre Gleitkommazahl wird tatsächlich durch drei ganze Zahlen dargestellt: ein Vorzeichenbit s
, einen Signifikanten (oder Koeffizienten / Bruch) b
und einen Exponenten e
. Beim Gleitkommaformat mit doppelter Genauigkeit wird jede Zahl durch 64 Bit dargestellt, die wie folgt im Speicher angeordnet sind:
Der reale Wert kann dann mit der folgenden Formel ermittelt werden:
Dieses Format ermöglicht Zahlendarstellungen im Bereich von 10 ^ -308 bis 10 ^ 308. Für MATLAB erhalten Sie diese Grenzwerte von realmin
und realmax
:
>> realmin
ans =
2.225073858507201e-308
>> realmax
ans =
1.797693134862316e+308
Da es eine endliche Anzahl von Bits gibt, die zur Darstellung einer Gleitkommazahl verwendet werden, gibt es nur so viele endliche Zahlen, die innerhalb des oben angegebenen Bereichs dargestellt werden können. Berechnungen führen häufig zu einem Wert, der nicht genau mit einer dieser endlichen Darstellungen übereinstimmt. Daher müssen die Werte gerundet werden. Diese Maschinengenauigkeitsfehler machen sich auf unterschiedliche Weise bemerkbar, wie in den obigen Beispielen erläutert.
Um diese Rundungsfehler besser zu verstehen, ist es nützlich, die relative Gleitkomma-Genauigkeit der Funktion zu betrachten eps
, die den Abstand von einer bestimmten Zahl zur nächstgrößeren Gleitkomma-Darstellung quantifiziert:
>> eps(1)
ans =
2.220446049250313e-16
>> eps(1000)
ans =
1.136868377216160e-13
Beachten Sie, dass die Genauigkeit relativ zur Größe einer bestimmten dargestellten Zahl ist. Größere Zahlen haben größere Abstände zwischen Gleitkommadarstellungen und daher weniger Genauigkeitsstellen nach dem Dezimalpunkt. Dies kann bei einigen Berechnungen eine wichtige Überlegung sein. Betrachten Sie das folgende Beispiel:
>> format long
>> x = rand(1, 10);
>> a = mean(x)
a =
0.587307428244141
>> b = mean(x+10000)-10000
b =
0.587307428244458
Beachten Sie, dass wir einen Wert erhalten, der sich für die letzten 3 signifikanten Stellen unterscheidet , wenn wir die Werte von x
vom Bereich [0 1]
in den Bereich verschieben [10000 10001]
, einen Mittelwert berechnen und dann den Mittelwertversatz zum Vergleich subtrahieren. Dies zeigt, wie ein Versatz oder eine Skalierung von Daten die Genauigkeit der daran durchgeführten Berechnungen ändern kann, was bei bestimmten Problemen berücksichtigt werden muss.