php float calculation 2 décimal point

a encore un problème de calcul.

$a = 34.56

$b = 34.55

$a faites un calcul pour obtenir ce chiffre

$b fait arrondi près de 0,05 pour obtenir ce chiffre

ce qui arrive est

$c = $b - $a

supposément je devrais être -0,01, mais je me fais l'écho du $c is show -0,009888888888

j'essaie d'utiliser n umber_format($c, 2) , mais la sortie est de 0,00,

Comment puis-je m'assurer que $a et $b est exactement 2 décimales, pas de nombre caché à l'arrière.

dans ma connaissance php number_format seulement capable de formater l'affichage, mais la valeur pas vraiment 2 décimal,

j'espère que je peux obtenir de l'aide d'ici. - Ce vraiment frustré moi.

16
demandé sur mskfisher 2009-10-22 06:14:46

7 réponses

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

les nombres à virgule flottante sont représentés en notation IEEE basée sur les pouvoirs de 2, donc les nombres décimaux terminaux peuvent ne pas être un nombre binaire terminal, c'est pourquoi vous obtenez les chiffres de queue.

comme suggéré par le codeur de longueur Variable, si vous connaissez la précision que vous voulez et il ne change pas (par exemple quand vous avez affaire à de l'argent) il pourrait être préférable d'utiliser juste point fixe nombre, c'est-à-dire exprimer les nombres en cents plutôt qu'en dollars

$a = 3456;

$b = 3455;

$c = $b - $a;

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

de cette façon, vous n'aurez pas d'erreurs d'arrondissement si vous faites beaucoup de calculs avant d'imprimer.

39
répondu Charles Ma 2014-01-31 20:09:24

Utilisation round() :

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

Note: vous pouvez également choisir le mode d'arrondissement, selon le cas.

Edit: Ok je ne comprends pas ce que sprintf() fait que number_format() n'est-ce pas:

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

vs

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

?

12
répondu cletus 2009-10-22 02:32:02

Calcul Natif:

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

fonctionne comme prévu (! utilisez toujours les fonctions BC pour les calculs de nombre réel, le problème est pour toutes les plates-formes basées C):

$a = '34.56';
$b = '34.55';
$c = bcsub($b, $a, 4); // -0.0100    
4
répondu PHP from Bulgaria 2013-04-04 14:55:11

vous avez rencontré l'un des pièges des nombres à virgule flottante; qu'ils ne peuvent pas toujours représenter des fractions décimales exactes. Si vous voulez des valeurs décimales exactes, il est préférable d'utiliser des nombres entiers et de les diviser par la précision que vous voulez à la fin.

par exemple, si vous faites des calculs en flotteurs représentant des Dollars (ou votre devise préférée), vous pouvez réellement faire vos calculs en cents entiers.

3
répondu Variable Length Coder 2009-10-22 02:34:20

vous pouvez très facilement contourner tous ces problèmes simplement en utilisant la bibliothèque bcmath.

n'oubliez pas de lire la documentation et faites attention si vous passez des arguments sous forme de chaînes ou de types de données numériques.

3
répondu Robert L 2010-02-17 05:48:40

j'ai aussi rencontré ce problème récemment en faisant des calculs avec des flotteurs. Par exemple, j'ai eu 2 flotteurs que lorsque soustrait et formaté, la valeur était -0.00.

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

ce que j'ai fait était:

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

dans ma solution je sais que floatOne ne sera jamais moins que floatTwo. La fonction money_format n'est définie que si le système possède des capacités strfmon, contrairement à Windows.

3
répondu jtaz 2014-03-21 14:55:08

si encore quelqu'un atteint cette page avec des problèmes similaires où la soustraction de nombre flottant provoque des valeurs d'erreur ou étranges. Je veux expliquer ce problème avec un peu plus de détails. Le coupable est le nombre de points flottants. Et différents systèmes d'exploitation et différentes versions de langages de programmation peuvent se comporter différemment.

pour illustrer le problème, je vais expliquer pourquoi avec un exemple simple ci-dessous.

il n'est pas directement lié à PHP et ce n'est pas un bug. Cependant, chaque programmeur devrait être conscient de cette question.

ce problème a même coûté de nombreuses vies il y a deux décennies.

le 25 février 1991, ce problème de calcul des nombres flottants dans une batterie de missiles Patriot MIM-104 l'a empêchée d'intercepter un missile Scud entrant à Dhahran, en Arabie Saoudite, contribuant à la mort de 28 soldats du 14e détachement de Quartier-maître de l'armée américaine.

But pourquoi ça arrive?

la raison en est que les valeurs en virgule flottante représentent une précision limitée. Donc, une valeur pourrait ont pas la même représentation de chaîne après le traitement. Il a également inclut l'écriture d'une valeur flottante dans votre script et directement l'impression sans opérations mathématiques.

juste un exemple simple:

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

vous vous attendez à ce qu'il imprime 0,01, Non? Mais il va imprimer une réponse très étrange comme 0.009999999999998

comme les autres nombres, les nombres à virgule flottante double ou float sont stockés en mémoire sous forme de chaîne de 0 et de 1. La différence entre un point flottant et un entier réside dans la façon dont nous interprétons les 0 et les 1 quand nous voulons les regarder. Il existe de nombreuses normes sur la façon de les stocker.

les nombres à virgule flottante sont généralement placés dans un datum d'ordinateur comme le bit de signe, le champ exposant, et le significand ou mantissa, de gauche à droit....

nombres décimaux ne sont pas bien représentés en binaire en raison du manque d'espace. Donc, uou ne peut pas exprimer 1/3 exactement comme il 0.3333333..., droit? Pourquoi nous ne pouvons pas représenter 0,01 comme un nombre flottant binaire est pour la même raison. 1/100 est 0.000000101000111101110000..... avec une répétition 10100011110101110000.

si 0,01 est conservé sous forme simplifiée et tronquée de 01000111101011100001010 en binaire, quand il est traduit à la décimale, il serait lu comme 0.0099999.... en fonction du système (les ordinateurs 64 bits vous donneront une bien meilleure précision que les 32 bits). Système d'exploitation décide, dans ce cas, si l'imprimer comme il voit ou comment le rendre plus lisible par l'homme. Donc, la façon dont ils veulent la représenter dépend de la machine. Mais il peut être protégé au niveau de la langue avec différentes méthodes.

si vous formatez le résultat, echo number_format(0.0099999999998, 2); il affichera 0.01.

c'est parce que dans ce cas vous donnez des instructions sur la façon de le lire et sur la précision dont vous avez besoin.

1
répondu Selay 2014-12-18 04:47:04