Table des matières
Résumé des points clés
Problème de Bcmath
cas 3
Bcmath Final Guidelines
MySQL et numéros de point fixe
Opérations mathématiques précises dans PHP et MySQL
Conclusion
Maison développement back-end tutoriel php Mathématiques à point fixe en PHP avec BCMATH, cas de perte de précision

Mathématiques à point fixe en PHP avec BCMATH, cas de perte de précision

Feb 20, 2025 am 09:17 AM

Fixed Point Math in PHP with BCMath, precision loss cases

Défis et conseils pour les opérations numériques à point fixe dans PHP et MySQL

Des soins extrêmes sont nécessaires lors de la gestion des valeurs de points fixes, en particulier lors du développement avec PHP et MySQL. Cet article explorera les obstacles et les détails rencontrés lors de l'utilisation d'extensions de PHP BCMATH, du traitement d'expression du point fixe MySQL et de la persistance des données de point fixe de PHP à MySQL. Malgré certains défis, nous essaierons de comprendre comment gérer les valeurs de points fixes et éviter les pertes de précision.

Résumé des points clés

  • L'extension BCMATH en PHP prend en charge les opérations mathématiques de précision arbitraire, mais peut entraîner une perte de précision si des variables numériques sont transmises à ses fonctions. Les valeurs de chaîne représentant les nombres doivent être utilisées à la place pour éviter ce problème.
  • MySQL prend en charge les expressions numériques à point fixe, cependant, si un opérande est au format exponentiel ou chaîne, il est considéré comme un numéro de point flottant. L'extension PHP PDO n'a pas de type de paramètre décimal pour la liaison, ce qui peut entraîner des résultats inexacts.
  • Pour effectuer des opérations mathématiques précises dans une application MySQL PHP, toutes les opérations peuvent être traitées en PHP et les données ne peuvent être persistées qu'à MySQL en utilisant des instructions d'insertion ou de mise à jour. Alternativement, vous pouvez créer manuellement les requêtes SQL pour vous assurer que toutes les expressions mathématiques SQL sont représentées en nombre décimales.

Problème de Bcmath

La documentation BCMath indique:

Pour les opérations de mathématiques de précision arbitraires, PHP fournit une calculatrice binaire qui prend en charge tous les nombres de taille et de précision exprimés en chaînes.

Par conséquent, les paramètres de fonction BCMATH doivent être représentés comme des chaînes. Passer une variable numérique à la fonction BCMATH peut entraîner un résultat incorrect, la même perte de précision que celle qui se produit lors du traitement d'une double valeur comme une chaîne.

cas 1

echo bcmul(776.210000, '100', 10) . PHP_EOL;
echo bcmul(776.211000, '100', 10) . PHP_EOL;
echo bcmul(776.210100, '100', 10) . PHP_EOL;

echo bcmul(50018850776.210000, '100', 10) . PHP_EOL;
echo bcmul(50018850776.211000, '100', 10) . PHP_EOL;
echo bcmul(50018850776.210100, '100', 10) . PHP_EOL;
Copier après la connexion
Copier après la connexion

Le résultat est:

<code>77621.00
77621.100
77621.0100
5001885077621.00
5001885077621.100
5001885077621.00 //此处可见精度损失</code>
Copier après la connexion
Copier après la connexion

Ne passez pas les variables numériques à la fonction BCMATH, seules les valeurs de chaîne représentant des nombres sont passées. Même si les nombres de points flottants ne sont pas traités, BCMath publiera des résultats étranges:

cas 2

echo bcmul('10', 0.0001, 10) . PHP_EOL;
echo bcmul('10', 0.00001, 10) . PHP_EOL;
echo 10*0.00001 . PHP_EOL;
Copier après la connexion
Copier après la connexion

Le résultat est:

<code>0.0010
0 // 这真的很奇怪!!!
0.0001</code>
Copier après la connexion

La raison en est que BCMATH convertit ses paramètres en chaînes, et dans certains cas, la représentation de chaîne des nombres a une représentation exponentielle.

cas 3

echo bcmul('10', '1e-4', 10) . PHP_EOL; // 也输出 0
Copier après la connexion

PHP est un langage de type faible qui, dans certains cas, n'a pas de contrôle strict sur l'entrée - réfléchit à la gestion du plus de demandes que possible.

Par exemple, nous pouvons "corriger" cas 2 et cas 3 :

$val = sprintf("%.10f", '1e-5');
echo bcmul('10', $val, 10) . PHP_EOL;
// 给我们 0.0001000000
Copier après la connexion

Cependant, l'application de la même transformation détruira le comportement "correct" de cas 1 :

$val = sprintf("%.10f", '50018850776.2100000000');
echo bcmul('10', $val, 10) . PHP_EOL;
echo bcmul('10', 50018850776.2100000000, 10) . PHP_EOL;
500188507762.0999908450 // 错误
500188507762.10 // 正确
Copier après la connexion

Ainsi, la solution sprintf ne fonctionne pas avec BCMATH. En supposant que toutes les entrées utilisateur sont des chaînes, nous pouvons implémenter un simple validateur qui capture les nombres de toutes les notations exponentielles et les convertit correctement. Cette technique est mise en œuvre dans des bingumbers PHP, nous pouvons donc passer en toute sécurité dans des paramètres comme 1E-20 et 50018850776.2101 sans perdre la précision.

Bcmath Final Guidelines

N'utilisez pas les nombres de points flottants comme paramètres de fonctionnement à point fixe dans les fonctions d'extension BCMath PHP. Utilisez uniquement des chaînes.

Lors de l'utilisation de l'opération d'extension BCMATH, faites attention aux paramètres de la notation exponentielle. La fonction BCMATH ne gère pas correctement les paramètres exponentiels (tels que "1E-8"), ils doivent donc être convertis manuellement. Faites attention de ne pas utiliser Sprintf ou des techniques de conversion similaires, car cela entraînera une perte de précision.

La bibliothèque PHP-Bignubers peut être utilisée, qui peut gérer les paramètres d'entrée sous forme exponentielle et fournir aux utilisateurs des opérations mathématiques à virgule fixe. Cependant, ses performances ne sont pas aussi bonnes que les extensions de BCMath, il s'agit donc d'un compromis entre des packages robustes et des performances.

MySQL et numéros de point fixe

Dans MySQL, les nombres de points fixes sont traités à l'aide du type de colonne décimale. Vous pouvez lire la documentation officielle MySQL pour les types de données et les opérations mathématiques précises.

La partie la plus intéressante est la façon dont MySQL gère les expressions:

Le traitement des expressions numériques dépend du type de valeur contenue dans l'expression:

S'il existe une approximation, l'expression est une approximation et est calculée en utilisant le fonctionnement du point flottant.

Si aucune approximation n'existe, l'expression ne contient que des valeurs exactes. Si une valeur exacte contient la partie fractionnaire (la valeur après le point décimal), l'expression est calculée en utilisant une arithmétique décimale précise avec une précision à 65 chiffres. Le mot «précision» est limité par ce qui peut être représenté en binaire. Par exemple, 1,0 / 3.0 peut être approximatif à 0,333… en utilisant une notation décimale, mais ne peut pas être écrit comme des nombres exacts, donc (1.0 / 3.0) * 3.0 est mal calculé comme 1,0.

Sinon, l'expression ne contient que des valeurs entières. L'expression est précise et est calculée en utilisant l'arithmétique entier avec la même précision que Bigint (64 bits).

Si une expression numérique contient une chaîne, elle est convertie en une valeur à virgule flottante à double précision et l'expression est une valeur approximative.

Il s'agit d'un court exemple qui démontre le cas de la partie décimale:

echo bcmul(776.210000, '100', 10) . PHP_EOL;
echo bcmul(776.211000, '100', 10) . PHP_EOL;
echo bcmul(776.210100, '100', 10) . PHP_EOL;

echo bcmul(50018850776.210000, '100', 10) . PHP_EOL;
echo bcmul(50018850776.211000, '100', 10) . PHP_EOL;
echo bcmul(50018850776.210100, '100', 10) . PHP_EOL;
Copier après la connexion
Copier après la connexion

Cela semble simple, mais voyons comment le gérer en php.

Opérations mathématiques précises dans PHP et MySQL

Alors maintenant, nous devons persister les valeurs de points fixes de PHP à MySQL. La bonne façon est d'utiliser des déclarations de prétraitement et des espaces réservés dans la requête. Ensuite, nous faisons la liaison des paramètres, tout est sûr et fiable.

<code>77621.00
77621.100
77621.0100
5001885077621.00
5001885077621.100
5001885077621.00 //此处可见精度损失</code>
Copier après la connexion
Copier après la connexion

Lorsque nous lions la valeur à l'espace réservé de l'instruction, nous pouvons spécifier son type via le troisième paramètre de BindValue. Les types possibles sont représentés par les constantes PDO :: Param_bool, PDO :: Param_null, PDO :: Param_int, PDO :: Param_str, PDO :: param_lob et PDO :: Param_stmt. Le problème est donc que l'extension PHP PDO n'a pas de type de paramètre décimal pour la liaison. En conséquence, toutes les expressions mathématiques dans la requête sont traitées comme des expressions de points flottants, plutôt que des expressions de points fixes.

Si nous voulons profiter des instructions de prétraitement et utiliser des numéros de point fixe, la meilleure façon est d'effectuer tous les mathématiques en PHP et d'enregistrer le résultat sur MySQL.

echo bcmul('10', 0.0001, 10) . PHP_EOL;
echo bcmul('10', 0.00001, 10) . PHP_EOL;
echo 10*0.00001 . PHP_EOL;
Copier après la connexion
Copier après la connexion

Conclusion

Nous sommes arrivés à la conclusion suivante:

  • N'utilisez pas les nombres de points flottants comme paramètres de fonctionnement à point fixe dans les fonctions d'extension BCMath PHP. Utilisez uniquement des chaînes.
  • L'extension bcmath ne s'applique pas aux numéros de chaîne pour la notation exponentielle.
  • MySQL prend en charge les expressions numériques à point fixe, mais tous les opérandes doivent être au format décimal. Si au moins un paramètre est au format exponentiel ou à chaîne, il est traité comme un numéro de point flottant et l'expression est calculée comme un numéro de point flottant.
  • L'extension PHP PDO n'a pas de type de paramètre décimal, donc si vous utilisez une instruction de prétraitement et liez les paramètres dans une expression SQL contenant des opérandes à point fixe, vous n'obtiendrez pas de résultats exacts.
  • Pour effectuer des opérations mathématiques précises dans une application PHP MySQL, vous pouvez choisir parmi deux méthodes. La première méthode consiste à traiter toutes les opérations en PHP et à utiliser uniquement des instructions d'insertion ou de mise à jour pour persister les données vers MySQL. Dans ce cas, vous pouvez utiliser des instructions prétraitées et des liaisons de paramètres. La deuxième approche consiste à construire manuellement les requêtes SQL (vous pouvez toujours utiliser des instructions de prétraitement, mais vous devez échapper aux paramètres vous-même) afin que toutes les expressions mathématiques SQL soient exprimées en chiffres décimaux.

Ma méthode préférée est la première: faites tous les mathématiques en php. Je suis d'accord que PHP et MySQL ne sont peut-être pas le meilleur choix pour les applications qui nécessitent des opérations mathématiques précises, mais si vous choisissez cette pile technologique, il est bon de savoir comment le gérer correctement.

(La pièce FAQ est omise en raison des limites de l'espace. Si nécessaire, la pièce FAQ peut être générée séparément.)

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!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

<🎜>: Grow A Garden - Guide de mutation complet
3 Il y a quelques semaines By DDD
<🎜>: Bubble Gum Simulator Infinity - Comment obtenir et utiliser les clés royales
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers of the Witch Tree - Comment déverrouiller le grappin
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Système de fusion, expliqué
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Tutoriel Java
1668
14
Tutoriel PHP
1273
29
Tutoriel C#
1256
24
PHP: un langage clé pour le développement Web PHP: un langage clé pour le développement Web Apr 13, 2025 am 12:08 AM

PHP est un langage de script largement utilisé du côté du serveur, particulièrement adapté au développement Web. 1.Php peut intégrer HTML, traiter les demandes et réponses HTTP et prend en charge une variété de bases de données. 2.PHP est utilisé pour générer du contenu Web dynamique, des données de formulaire de traitement, des bases de données d'accès, etc., avec un support communautaire solide et des ressources open source. 3. PHP est une langue interprétée, et le processus d'exécution comprend l'analyse lexicale, l'analyse grammaticale, la compilation et l'exécution. 4.PHP peut être combiné avec MySQL pour les applications avancées telles que les systèmes d'enregistrement des utilisateurs. 5. Lors du débogage de PHP, vous pouvez utiliser des fonctions telles que error_reportting () et var_dump (). 6. Optimiser le code PHP pour utiliser les mécanismes de mise en cache, optimiser les requêtes de base de données et utiliser des fonctions intégrées. 7

Expliquez le hachage de mot de passe sécurisé dans PHP (par exemple, Password_Hash, Password_verify). Pourquoi ne pas utiliser MD5 ou SHA1? Expliquez le hachage de mot de passe sécurisé dans PHP (par exemple, Password_Hash, Password_verify). Pourquoi ne pas utiliser MD5 ou SHA1? Apr 17, 2025 am 12:06 AM

Dans PHP, Password_Hash et Password_verify Les fonctions doivent être utilisées pour implémenter le hachage de mot de passe sécurisé, et MD5 ou SHA1 ne doit pas être utilisé. 1) Password_hash génère un hachage contenant des valeurs de sel pour améliorer la sécurité. 2) Password_verify Vérifiez le mot de passe et assurez-vous la sécurité en comparant les valeurs de hachage. 3) MD5 et SHA1 sont vulnérables et manquent de valeurs de sel, et ne conviennent pas à la sécurité de mot de passe moderne.

PHP et Python: comparaison de deux langages de programmation populaires PHP et Python: comparaison de deux langages de programmation populaires Apr 14, 2025 am 12:13 AM

PHP et Python ont chacun leurs propres avantages et choisissent en fonction des exigences du projet. 1.Php convient au développement Web, en particulier pour le développement rapide et la maintenance des sites Web. 2. Python convient à la science des données, à l'apprentissage automatique et à l'intelligence artificielle, avec syntaxe concise et adaptée aux débutants.

PHP en action: Exemples et applications du monde réel PHP en action: Exemples et applications du monde réel Apr 14, 2025 am 12:19 AM

PHP est largement utilisé dans le commerce électronique, les systèmes de gestion de contenu et le développement d'API. 1) E-commerce: Utilisé pour la fonction de panier et le traitement des paiements. 2) Système de gestion du contenu: utilisé pour la génération de contenu dynamique et la gestion des utilisateurs. 3) Développement des API: Utilisé pour le développement de l'API RESTful et la sécurité de l'API. Grâce à l'optimisation des performances et aux meilleures pratiques, l'efficacité et la maintenabilité des applications PHP sont améliorées.

Comment fonctionne la résistance au type PHP, y compris les types scalaires, les types de retour, les types d'union et les types nullables? Comment fonctionne la résistance au type PHP, y compris les types scalaires, les types de retour, les types d'union et les types nullables? Apr 17, 2025 am 12:25 AM

Le type PHP invite à améliorer la qualité et la lisibilité du code. 1) Conseils de type scalaire: Depuis PHP7.0, les types de données de base sont autorisés à être spécifiés dans les paramètres de fonction, tels que INT, Float, etc. 2) Invite de type de retour: Assurez la cohérence du type de valeur de retour de fonction. 3) Invite de type d'union: Depuis PHP8.0, plusieurs types peuvent être spécifiés dans les paramètres de fonction ou les valeurs de retour. 4) Invite de type nullable: permet d'inclure des valeurs nulles et de gérer les fonctions qui peuvent renvoyer les valeurs nulles.

La pertinence durable de PHP: est-elle toujours vivante? La pertinence durable de PHP: est-elle toujours vivante? Apr 14, 2025 am 12:12 AM

PHP est toujours dynamique et occupe toujours une position importante dans le domaine de la programmation moderne. 1) La simplicité de PHP et le soutien communautaire puissant le rendent largement utilisé dans le développement Web; 2) sa flexibilité et sa stabilité le rendent exceptionnelle dans la gestion des formulaires Web, des opérations de base de données et du traitement de fichiers; 3) PHP évolue et optimise constamment, adapté aux débutants et aux développeurs expérimentés.

PHP vs autres langues: une comparaison PHP vs autres langues: une comparaison Apr 13, 2025 am 12:19 AM

PHP convient au développement Web, en particulier dans le développement rapide et le traitement du contenu dynamique, mais n'est pas bon dans les applications de la science des données et de l'entreprise. Par rapport à Python, PHP présente plus d'avantages dans le développement Web, mais n'est pas aussi bon que Python dans le domaine de la science des données; Par rapport à Java, PHP fonctionne moins bien dans les applications au niveau de l'entreprise, mais est plus flexible dans le développement Web; Par rapport à JavaScript, PHP est plus concis dans le développement back-end, mais n'est pas aussi bon que JavaScript dans le développement frontal.

PHP et Python: différents paradigmes expliqués PHP et Python: différents paradigmes expliqués Apr 18, 2025 am 12:26 AM

PHP est principalement la programmation procédurale, mais prend également en charge la programmation orientée objet (POO); Python prend en charge une variété de paradigmes, y compris la POO, la programmation fonctionnelle et procédurale. PHP convient au développement Web, et Python convient à une variété d'applications telles que l'analyse des données et l'apprentissage automatique.

See all articles