Le contenu de cet article concerne l'analyse du code de précision décimale en PHP. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Problèmes de précision rencontrés lors de l'arrondi à deux décimales dans le projet :
$num = 0.99; $num1 = round($num, 2);//0.98999999999999999 $num2 = floatval($num);//0.98999999999999999
Solution actuelle :
sprintf("%.2f", round($money, 2));//会自动四舍五入 echo substr(sprintf("%.3f",$n), 0, -1);//不四舍五入
Résultats des tests :
var_dump(json_encode(round(0.99 ,2)));//0.98999999999999999 var_dump(round(0.99 ,2));//0.99 $f = 0.58; var_dump(intval($f * 100));//57
Concernant la problématique de égal à 57, on peut l'analyser :
Représentation des nombres à virgule flottante (IEEE 754 : IEEE Binary Floating Point Arithmetic Standard) :
Nombres à virgule flottante, avec un longueur de 64 bits (Double précision) à titre d'exemple, il sera représenté par 1 bit de signe (E), 11 bits d'exposant (Q) et 52 bits de mantisse (M) (un total de 64 bits
<). 🎜> Bit de signe : le bit le plus élevé représente les données Le positif et le négatif de , 0 représente un nombre positif et 1 représente un nombre négatif. Bit exposant : représente la puissance des données en base 2, l'exposant est représenté par un code offset Mantisse : représente les chiffres significatifs après la virgule décimale 0,58 pour la représentation binaire Par exemple, c'est une valeur infiniment longue : La représentation binaire de 0,58 est essentiellement (52 bits) : 0010100011110101110000101000111101011100001010001111 La représentation binaire de 0 .57 est essentiellement ( 52 bits) est : 001000111101011100001010001111010111000010100011110Et les nombres binaires des deux, s'ils sont calculés uniquement par ces 52 bits, sont : 0,58 --> 9999999960,57 -- > 0,5699999999 999999 Ainsi, le résultat de 0,58 * 100 sera : 57,999999999, converti en entier : 57Pour la représentation binaire des nombres à virgule flottante, vous pouvez vous référer à : Représentation binaire de nombres à virgule flottanteSimilaire à :
(0.1 + 0.7) == 0.8//false floor((0.1+0.7)*10)//7 //内部结果可能是:7.9999999999 //所以:不可能精确的用有限位数表达某些十进制分数 1/3=3.33333333333 //而3.333333333333333*3,却不是1
Ne croyez donc jamais que le résultat d'un nombre à virgule flottante est précis jusqu'au dernier chiffre, et ne comparez jamais deux nombres à virgule flottante pour voir s'ils sont égaux. Si vous avez vraiment besoin d'une plus grande précision, vous devez utiliser des fonctions mathématiques de précision arbitraire ou des fonctions gmp
Il est recommandé d'utiliser des fonctions de haute précision : Fonctions de haute précisionfunction getBcRound($number, $precision = 0) { $precision = ($precision < 0) ? 0 : (int) $precision; if (strcmp(bcadd($number, '0', $precision), bcadd($number, '0', $precision+1)) == 0) { return bcadd($number, '0', $precision); } if (getBcPresion($number) - $precision > 1) { $number = getBcRound($number, $precision + 1); } $t = '0.' . str_repeat('0', $precision) . '5'; return $number < 0 ? bcsub($number, $t, $precision) : bcadd($number, $t, $precision); } function getBcPresion($number) { $dotPosition = strpos($number, '.'); if ($dotPosition === false) { return 0; } return strlen($number) - strpos($number, '.') - 1; } $money = getBcRound(0.99, 2);
Analyse de fichiers cryptés AES en PHP (avec code)
Demander des codes pour le mode publication et obtenir le mode dans curl de php
À propos de l'analyse du contenu des touches centrales PHP
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!