Mysql
 sql >> Base de données >  >> RDS >> Mysql

Précision décimale MySQL et PHP incorrecte

De un article que j'ai écrit pour Authorize.Net :

Un plus un égale deux, n'est-ce pas ? Que diriez-vous de 0,2 plus 1,4 fois 10 ? Cela équivaut à 16, n'est-ce pas ? Pas si vous faites le calcul avec PHP (ou la plupart des autres langages de programmation) :

echo floor((0.2 + 1.4) * 10); // Should be 16. But it's 15!

Cela est dû à la façon dont les nombres à virgule flottante sont gérés en interne. Ils sont représentés avec un nombre fixe de décimales et peuvent donner des nombres qui ne s'additionnent pas tout à fait comme prévu. En interne, notre exemple .2 plus 1,4 fois 10 calcule environ 15,9999999998 environ. Ce type de calcul convient bien lorsque vous travaillez avec des nombres qui n'ont pas besoin d'être précis comme des pourcentages. Mais lorsque vous travaillez avec de l'argent, la précision compte, car un sou ou un dollar manquant ici ou là s'additionne rapidement et personne n'aime être à court d'argent manquant.

La solution mathématique de la Colombie-Britannique

Heureusement, PHP propose l'l'extension BC Math qui est "pour les mathématiques de précision arbitraire, PHP propose la calculatrice binaire qui prend en charge les nombres de n'importe quelle taille et précision, représentés sous forme de chaînes". En d'autres termes, vous pouvez faire des calculs précis avec des valeurs monétaires en utilisant cette extension. L'extension BC Math contient une fonction s qui vous permettent d'effectuer les opérations les plus courantes avec précision, y compris ajout , soustraction , multiplication , et division .

Un meilleur exemple

Voici le même exemple que ci-dessus mais en utilisant la fonction bcadd() pour faire le calcul pour nous. Il prend trois paramètres. Les deux premiers sont les valeurs que nous souhaitons ajouter et le troisième est le nombre de décimales auxquelles nous souhaitons être précis. Puisque nous travaillons avec de l'argent, nous allons définir la précision sur deux décimales.

echo floor(bcadd('0.2', '1.4', 2) * 10); // It's 16 like we would expect it to be.