2010-11-19 2 views
0

Mögliche Duplizieren:
compare floats in phpPHP findet nicht zwei gleiche Zahlen, um gleich zu sein? Fehler?

ich habe eine Bedingung:

if($x <= .3) 
    echo 1; 

es 1 Echo wird nur dann, wenn x kleiner als 0,3

wenn $ x ist gleich .3, ich bekomme keine 1.

Ich habe versucht, die x in floatval() Wickeln, aber kein Glück

Ich habe versucht, die $ x Echo und ich erhalte "0,3"

i if ($x == .3) versucht haben - nichts

wenn i haben if (.3 == .3) versucht, die

Ideen offensichtlich funktioniert? Ist das ein PHP Bug?

+1

Es ist kein Fehler. Könnte jemand bitte ein Duplikat finden, um das zu schließen? –

+0

Woher wissen Sie, dass $ x 0,3 ist, z. ist der gesamte Code $ x = .3; if ($ x <=. 3) echo 1? –

+0

Bitte geben Sie eine Zuweisung von $ x – erenon

Antwort

1

Fließkommawerte nicht exakt sind. Sie können prüfen, ob es etwa < = 0,3 wie folgt ist:

if ($x <= 0.3000001) { 
    echo 'yay'; 
} 
+0

wow - warum ist das so? also 12.8-12.5 ist wirklich nicht .3 - obwohl es als .3 druckt? Ich muss mit dem Kunden überprüfen, aber hoffentlich arbeitet er nur in 2-stelliger Genauigkeit – dan

+0

Dies ist eine ziemlich kompetente Erklärung, die auf sich selbst baut, wie es geht: http://support.microsoft.com/kb/42980 – dkamins

+0

BTW Sie müssen nicht wirklich genau verstehen, warum, wenn Sie besonders neugierig sind. Die Hauptsache ist die allgemeine Regel, dass in 99% der Fälle Fließkommazahlen nicht direkt mit Gleichheitsoperatoren verglichen werden sollten. Ganzzahlen können natürlich sein (weil sie direkt im Binärformat dargestellt werden können). – dkamins

0

hmmm, ich muss davon ausgehen, dass Ihre var $x wirklich nicht gleich .3 ist.

i getestet gerade dieses:

<? 
    $var = 0.3; 

    if($var <= .3) 
    { 
     echo 'yay'; 
    } 
    else 
    { 
     echo 'boo'; 
    } 
?> 

und es gibt yay

+0

Natürlich ist es nicht. Weil 0.3 in den meisten Computern nicht wirklich existieren kann. –

+0

das funktioniert, aber meine Variable ist tatsächlich von $ x = 12.8-12.5 erstellt, die nicht funktioniert. – dan

0

$ x = 0,4;
if ($ x < = .3) {echo 1; }
Funktioniert hier gut ... versucht, verschiedene Werte bei $ x
aber ... wo Sie $ x bekommen ?? Möglicherweise müssen Sie den Wert vor dem Vergleich runden.

4

Es geht um Binärdarstellung von Gleitkommazahlen:

var_dump(sprintf("%.40f", 0.3)); 
// string(42) "0.2999999999999999888977697537484345957637" 

Grundsätzlich kann 0,3 nicht genau in 2 Basis dargestellt werden, so wird sie nach einigen Stellen abgeschnitten. Es ist im Grunde wie 1/3 in der Basis 10: Sie können 0,3 eingeben, aber 0,33 ist genauer, so ist 0,333, 0,3333 usw. Sie können es nicht genau darstellen.

0

Schwimmdock Punkte sind nicht 100% genau. Kurz gesagt, die gebrochene Komponente wird im allgemeinen durch Hinzufügen von 1/(2^n) zusammen gespeichert. z.B. 1/2 + 1/4 ist, wie 3/4 gespeichert würde. Das ist also kein Bug, noch ist es eine spezielle PHP-Frage.

Dies sollte jedoch immer wahr sein:

$x = 0.3; 
if ($x == 0.3) echo "true"; 

weil die gleiche Ungenauigkeit in beiden vorhanden sein würde.

Aber das ist nicht wahr sein garantiert:

$x = 0.1; 
$y = 0.2; 
if ($x + $y == 0.3) echo "true"; 

Eine einfache Möglichkeit, dies zu umgehen, ein Delta zu verwenden ist:

if (abs($a - $b) < $delta) echo "true" 

wo delta $ eine sehr kleine Zahl ist.

Wenn Sie Genauigkeit benötigen, dann schauen Sie sich die BCMath-Erweiterung an.

Wenn dies für Geld ist, dann ist es in der Regel einfacher, nur Berechnungen in ganzem Cent (Integer), wobei 1,23 $ = 123.

1

Hier, groß, rot und Fett: Floating Point Numbers:

Es ist typisch, dass einfache dezimal Fraktionen wie 0,1 oder 0,7 nicht ohne einen kleinen Verlust von Präzision in ihre internen binären Pendants umgewandelt werden. Dies kann zu verwirrend Ergebnissen führen: zum Beispiel Boden ((0,1 + 0,7) * 10) wird in der Regel zurückgeben 7 statt der erwarteten 8, seit der internen Darstellung wird etwa 7.9 sein.

Dies ist auf die Tatsache zurückzuführen, dass es unmöglich ist, einige Fraktionen in Dezimalschreibweise mit einer endlichen Anzahl von Ziffern auszudrücken. Zum Beispiel wird 1/3 in Dezimalform 0,3.

So vertrauen nie Zahl schwebenden Ergebnisse auf die letzte Stelle, und nie Gleitkommazahlen für die Gleichstellung vergleichen. Wenn eine höhere Genauigkeit erforderlich ist, stehen die Funktionen arbitrary precision math functions und gmp zur Verfügung.

PS: Es gibt noch mehr Spaß:

INF == INF => false 
INF < INF => true 
INF > INF => true 

So unendlich ist nicht unendlich und unendlich kleiner als unendlich und größer als unendlich zugleich. Wenn Sie darüber nachdenken, macht es tatsächlich einen Sinn ...

Verwandte Themen