Frage

Haben Sie eine andere mathematische Berechnung Problem wieder.

$a = 34.56

$b = 34.55

$a tun einige Berechnung dieser Zahl zu erhalten

$b runden dabei auf 0,05, diese Zahl zu bekommen

, was geschehen ist

$c = $b - $a

angeblich soll ich sein -0,01, aber ich echo die $c ist Show -,00988888888888

Ich versuche number_format($c, 2) zu verwenden, aber der Ausgang ist 0,00,

Wie kann ich sicher $a machen und $b ist genau 2 Dezimalstellen, keine versteckte Nummer auf der Rückseite.

in meiner PHP-Kenntnissen number_format nur in der Lage die Anzeige zu formatieren, aber der Wert nicht wirklich 2 dezimal,

Ich hoffe, dass ich Hilfe von hier bekommen. Das ist wirklich frustriert mich.

War es hilfreich?

Lösung

Versuchen Sie sprintf ("%.2f", $c);

Gleitkommazahlen wird in IEEE Notation dargestellt, basierend auf den Potenzen von 2, so Dezimalzahlen endet nicht eine Beendigung binäre Zahl sein, das ist, warum Sie die hinteren Ziffern erhalten.

Wie Variable Length Coder vorgeschlagen, wenn Sie die Präzision, die Sie wünschen und es ändert sich nicht (zum Beispiel, wenn Sie mit Geld zu tun hat) es besser sein könnte, nur um Festpunktzahlen verwenden, dh die Zahlen als Cent ausdrücken eher als Dollar

$a = 3456;

$b = 3455;

$c = $b - $a;

sprintf ("%.2f", $c/100.0);

Auf diese Weise werden Sie Rundungsfehler nicht haben, wenn Sie eine Menge von Berechnungen vor dem Druck.

Andere Tipps

Verwenden Sie round() :

$c = round($b - $a, 2);

. Hinweis: Sie können auch den Rundungsmodus entsprechend wählen

Edit: Ok ich nicht bekommen, was sprintf() dass number_format() tut nicht:

$c = number_format($b - $a, 2);

vs

$c = sprintf("%.2f", $b - $a);

Native Berechnung:

$a = 34.56;
$b = 34.55;
$c = $b - $a; // -0.010000000000005    

wie erwartet funktioniert (! Verwendet immer BC Funktionen für Berechnungen mit reellen Zahlen, ist die Frage für alle C-basierten Plattformen):

$a = '34.56';
$b = '34.55';
$c = bcsub($b, $a, 4); // -0.0100    

Ich lief auch in dieser Ausgabe vor kurzem, als Berechnungen mit Schwimmern zu tun. Zum Beispiel hatte ich zwei Schwimmern, dass, wenn abgezogen und formatiert war der Wert -0,00.

$floatOne = 267.58;
$floatTwo = 267.58;
$result = number_format($floatOne - floatTwo, 2);
print $result; //printed a string -0.00

Was ich tat, war:

$result = abs($floatOne - $floatTwo);// Made the number positive
print money_format('%i', $result); // printed the desired precision 0.00

In meiner Lösung weiß ich, dass floatOne nie als floatTwo weniger sein. Die money_format Funktion nur definiert, wenn die Systemfähigkeiten strfmon hat, Windows nicht.

Sie haben in eine der Fallen laufen von Gleitkommazahlen; dass sie genaue Dezimaltrennzeichen vertreten Fraktionen nicht immer. Wenn Sie genaue Dezimalwerte wollen, sind Sie besser dran, ganze Zahlen und anschließend durch die Präzision Dividieren Sie am Ende wollen.

Zum Beispiel, wenn Sie Berechnungen in Schwimmern represeting Dollar tun (oder Ihre bevorzugte Währung), können Sie wollen tatsächlich tun, um Ihre Berechnungen in Integer-Cent.

Sie können sehr fein säuberlich alle diese Probleme umgehen, indem einfach die bcmath Bibliothek.

Denken Sie daran, die Dokumentation zu lesen und darauf achten, ob Sie Argumente als Strings oder als numerische Datentypen sind vorbei.

Wenn jemand noch diese Seite mit ähnlichen Problemen erreichen, wo Subtraktionszahl schwebenden verursacht Fehler oder seltsame Werte. Ich will dieses Problem mit einem bisschen mehr Details erklären. Schuld daran sind die Gleitkommazahlen. Und verschiedene Betriebssysteme und verschiedene Versionen von Programmiersprachen können sich anders verhalten.

Um das Problem zu veranschaulichen, werde ich erklären, warum mit einem einfachen Beispiel unten.

Es ist nicht direkt mit PHP verwendet und es ist kein Fehler. jeder Programmierer sollte jedoch sein, sich dieses Problems bewusst.

Dieses Problem hat auch viele Leben vor zwei Jahrzehnten.

Am 25. Februar 1991 dieses Problem Nummer Berechnung in einer MIM-104 Patriot-Raketenbatterie in floating verhinderte es eine eingehende Scud-Rakete in Dhahran, Saudi-Arabien abfängt, einen Beitrag zum Tod von 28 Soldaten aus der 14. Rüstmeister Detachment US-Armee.

Aber warum es passiert?

Der Grund dafür ist, dass Gleitkommazahlen eine begrenzte Genauigkeit darstellen. So könnte ein Wert hat die gleiche String-Darstellung nicht nach jeder Verarbeitung. es ist auch einen Fließkommawert in Ihrem Skript enthält das Schreiben und direkt Drucken es ohne mathematische Operationen.

Nur ein einfaches Beispiel:

$a = '36';
$b = '-35.99';
echo ($a + $b);

Sie würden erwarten, dass es 0,01 zu drucken, nicht wahr? Aber es wird eine sehr merkwürdige Antwort wie ,009999999999998 drucken

Wie andere Zahlen, Gleitkommazahlen doppelter oder Schwimmer wird im Speicher als eine Folge von 0 und 1 ist gespeichert. Wie Gleitkomma von integer unterscheidet, ist, wie wir die 0 und 1 ist zu interpretieren, wenn wir sie sehen wollen. Es gibt viele Standards, wie sie gespeichert sind.

Gleitkommazahlen werden in der Regel in einen Computer Datum als das Vorzeichenbit, das Exponentenfeld gepackt, und der Mantisse oder Mantisse, von links nach rechts ....

Dezimalzahlen sind nicht gut binär dargestellt wegen des Mangels an ausreichend Platz. So kann uou nicht 1/3 genau auszudrücken, wie es 0,3333333 ist ..., nicht wahr? Warum können wir nicht 0,01 repräsentieren als eine binäre Gleitkommazahl aus dem gleichen Grunde ist. 1/100 ist 0,00000010100011110101110000 ..... mit einem 10100011110101110000 wiederholen.

Wenn 0,01 in vereinfachter und system verkürzte Form von 01000111101011100001010 binär gehalten wird, wenn es wieder in Dezimalzahlen übersetzt wird, wäre es wie 0,0099999 gelesen werden .... je nach System (64-Bit-Computer geben Ihnen viele bessere Präzision als 32-Bit). Betriebssystem entscheidet in diesem Fall, ob es zu drucken, wie es sieht oder wie man es macht in menschenlesbare Art und Weise. Also, es ist maschinenabhängig, wie sie es darstellen wollen. Aber es kann mit verschiedenen Methoden in Sprachniveau geschützt werden.

Wenn Sie das Ergebnis zu formatieren, Echo number_format (,009999999999998, 2); es wird 0,01 drucken.

Es ist, weil in diesem Fall, dass Sie anweisen, wie sie gelesen werden sollen und wie Präzision, die Sie benötigen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top