In PHP war der Vergleich der Gleitkomma-Zahlen immer ein schwieriges Problem. Aufgrund der Genauigkeitsbegrenzung von Gleitkomma-Zahlen kann die Verwendung von == oder === direkt zum Vergleich von Gleitkomma-Zahlen zu ungenauen Ergebnissen führen. Daher empfehlen viele PHP -Entwickler die Verwendung der BCComp () -Funktion, um schwimmende Punktvergleiche durchzuführen. In diesem Artikel wird detailliert analysiert, warum empfohlen wird, BCCOMM () anstelle von == oder === zu verwenden, um schwimmende Punktzahlen zu vergleichen.
In Computern werden häufig schwimmende Punktzahlen verwendet, um reelle Zahlen darzustellen, die normalerweise durch den IEEE 754 -Standard dargestellt werden. Da die Floating-Punkt-Zahlen ungefähr durch binäre Zahlen mit endlichen Ziffern dargestellt werden, repräsentiert es häufig bestimmte Dezimalzahlen nicht genau. Beispielsweise kann 0,1 in einem Computer nicht genau wie 0,1 ausgedrückt werden, es ist tatsächlich eine Zahl nahe 0,1 , und dieser Genauigkeitsfehler kann sich in der Berechnung allmählich ansammeln.
Bei Verwendung von == oder === zum Vergleich von Schwimmpunktzahlen, wenn die Genauigkeit zwischen den beiden Gleitkommazahlen geringfügig besteht, können die Vergleichsergebnisse schlechter sein als erwartet. Zum Beispiel:
<span><span><span class="hljs-variable">$a</span></span><span> = </span><span><span class="hljs-number">0.1</span></span><span> + </span><span><span class="hljs-number">0.2</span></span><span>;
</span><span><span class="hljs-variable">$b</span></span><span> = </span><span><span class="hljs-number">0.3</span></span><span>;
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$a</span></span><span> == </span><span><span class="hljs-variable">$b</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"gleich"</span></span><span>;
} </span><span><span class="hljs-keyword">else</span></span><span> {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"不gleich"</span></span><span>;
}
</span></span>
Der obige Code kann in einigen Umgebungen "ungleich" ausgeben, da 0,1 + 0,2 in einem Computer nicht genau 0,3 entsprechen, was die Manifestation des Problems der schwimmenden Punktgenauigkeit ist.
BCCOMP () ist eine Funktion in PHP, die speziell zum Vergleich von Gleitpunktzahlen mit willkürlicher Genauigkeit verwendet wird. Es unterscheidet sich von der normalen == und === , bccomp () vergleicht eine Zeichenfolge, die die schwimmenden Punktzahlen darstellt, und ermöglicht es Ihnen, die Genauigkeit des Vergleichs anzugeben.
Die Syntax der Funktion bccomp () lautet wie folgt:
<span><span><span class="hljs-title function_ invoke__">bccomp</span></span><span>(</span><span><span class="hljs-keyword">string</span></span><span> </span><span><span class="hljs-variable">$left_operand</span></span><span>, </span><span><span class="hljs-keyword">string</span></span><span> </span><span><span class="hljs-variable">$right_operand</span></span><span>, </span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-variable">$scale</span></span><span> = </span><span><span class="hljs-number">0</span></span><span>): </span><span><span class="hljs-keyword">int</span></span><span>
</span></span>
$ links_operand und $ right_operand sind zwei schwimmende Punktzahlen, die verglichen werden müssen und müssen als Zeichenfolge übergeben werden.
Der Parameter $ scale gibt die maximale Anzahl der Ziffern nach dem Dezimalpunkt an, dh die im Vergleich beibehaltene Genauigkeit.
BCCOMM () -Funktion gibt einen Ganzzahlwert zurück:
Wenn der erste Parameter größer als der zweite Parameter ist, geben Sie 1 zurück;
Wenn die beiden Parameter gleich sind, geben Sie 0 zurück;
Wenn der erste Parameter kleiner als der zweite Parameter ist, geben Sie -1 zurück.
Durch die Verwendung von BCCOMP () können wir sicherstellen, dass die Genauigkeit von Gleitkomma-Vergleiche innerhalb des erwarteten Bereichs gesteuert wird, anstatt durch die Floating-Punkt-Repräsentationsfehler der Computer-Punkte zu beeinflussen.
Um Gleitkomma-Nummern mit BCCOMM () zu vergleichen, müssen wir die Gleitkomma-Nummern in das String-Format konvertieren und die entsprechende Genauigkeit festlegen. Zum Beispiel:
<span><span><span class="hljs-variable">$a</span></span><span> = </span><span><span class="hljs-number">0.1</span></span><span> + </span><span><span class="hljs-number">0.2</span></span><span>;
</span><span><span class="hljs-variable">$b</span></span><span> = </span><span><span class="hljs-number">0.3</span></span><span>;
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">bccomp</span></span><span>((</span><span><span class="hljs-keyword">string</span></span><span>)</span><span><span class="hljs-variable">$a</span></span><span>, (</span><span><span class="hljs-keyword">string</span></span><span>)</span><span><span class="hljs-variable">$b</span></span><span>, </span><span><span class="hljs-number">10</span></span><span>) == </span><span><span class="hljs-number">0</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"gleich"</span></span><span>;
} </span><span><span class="hljs-keyword">else</span></span><span> {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"不gleich"</span></span><span>;
}
</span></span>
In diesem Beispiel konvertieren wir die schwimmenden Punktzahlen $ A und $ B in eine Zeichenfolge und setzen die Präzision auf 10 Bit. Dies vermeidet fehlerhafte Vergleiche aufgrund ungenauer schwimmender Punktdarstellungen.
Mit BCCOMP () können Sie die Genauigkeit des Vergleichs über den Parameter $ scale angeben. Dies ist besonders wichtig für schwimmende Punktzahlen, die Finanzen, wissenschaftliches Computer und andere Bereiche betreffen. In diesen Bereichen ist die Genauigkeit der Gleitkomma-Zahlen hoch, daher ist ein genauer Vergleich von entscheidender Bedeutung.
Beispielsweise können in Finanzanträgen schwimmende Werte wie Preis und Betrag nach dem Dezimalpunkt mehrere Ziffern beinhalten. Wenn die Genauigkeit nicht kontrolliert wird, kann dies zu einigen subtilen Fehlern führen, z. B. ein paar Cent weniger oder sogar logische Fehler.
<span><span><span class="hljs-variable">$price1</span></span><span> = </span><span><span class="hljs-string">"10.005"</span></span><span>;
</span><span><span class="hljs-variable">$price2</span></span><span> = </span><span><span class="hljs-string">"10.00499"</span></span><span>;
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">bccomp</span></span><span>(</span><span><span class="hljs-variable">$price1</span></span><span>, </span><span><span class="hljs-variable">$price2</span></span><span>, </span><span><span class="hljs-number">4</span></span><span>) == </span><span><span class="hljs-number">0</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"价格gleich"</span></span><span>;
} </span><span><span class="hljs-keyword">else</span></span><span> {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"价格不gleich"</span></span><span>;
}
</span></span>
In diesem Beispiel können wir durch Einstellen der Genauigkeit auf 4 sicherstellen, dass bei der Durchführung von Preisvergleichs keine Fehler durch Genauigkeitsprobleme verursacht werden.
Obwohl == und === in PHP sehr häufig sind, sind sie nicht für schwimmende Punktvergleiche geeignet. Die spezifischen Gründe sind wie folgt:
== : Die beiden Operanden sind während des Vergleichs vom Typ konvertiert, was zu unerwünschten Ergebnissen führen kann. Beim Vergleich von Floating-Punkt-Zahlen ignoriert == das Genauigkeitsproblem und kümmert sich nur darum, ob die beiden Werte gleich sind. Dieser Vergleich kann jedoch zu Fehlern aufgrund des Darstellungsfehlers der Gleitkomma-Zahlen führen.
=== : == Es wird keine Typumwandlung durchgeführt, aber es erfordert, dass zwei Schwimmpunktzahlen nicht nur gleiche Werte haben, sondern auch genau den gleichen Typ und die gleiche Darstellung haben. Aufgrund des Genauigkeitsfehlers der schwimmenden Punktzahlen kann === falsch falsch zurückgeben, wenn die beiden Werte sehr nahe sind.
Zum Beispiel:
<span><span><span class="hljs-variable">$a</span></span><span> = </span><span><span class="hljs-number">0.1</span></span><span> + </span><span><span class="hljs-number">0.2</span></span><span>;
</span><span><span class="hljs-variable">$b</span></span><span> = </span><span><span class="hljs-number">0.3</span></span><span>;
</span><span><span class="hljs-title function_ invoke__">var_dump</span></span><span>(</span><span><span class="hljs-variable">$a</span></span><span> == </span><span><span class="hljs-variable">$b</span></span><span>); </span><span><span class="hljs-comment">// false</span></span><span>
</span><span><span class="hljs-title function_ invoke__">var_dump</span></span><span>(</span><span><span class="hljs-variable">$a</span></span><span> === </span><span><span class="hljs-variable">$b</span></span><span>); </span><span><span class="hljs-comment">// false</span></span><span>
</span></span>
Gerade an der Existenz von Floating - Punkt-Genauigkeitsfehlern, ist es nicht immer zuverlässig, die Floating -Punkt-Zahlen zu vergleichen, um die Gleitkomma-Zahlen zu vergleichen.
Aufgrund der Genauigkeitsbegrenzung von Gleitkomma-Zahlen kann die Verwendung von == oder === , um die Gleitkomma-Zahlen direkt zu vergleichen, direkt zu ungenauen Ergebnissen führen. Um dieses Problem zu lösen, wird empfohlen, die BCComp () -Funktion zu verwenden, die eine genauere Methode zum Vergleich der Gleitkomma-Zahlen bietet und es den Entwicklern ermöglicht, die Genauigkeit des Vergleichs zu steuern, wodurch potenzielle Fehler vermieden werden, die durch eine ungenaue Darstellung von Gleitkomma-Zahlen verursacht werden. In Szenarien mit hochpräzisen Vergleiche ist BCCOMP () eine zuverlässigere und sicherere Wahl.