Php qui fait des calculs faux
Fermé
julienvo
Messages postés
5
Date d'inscription
jeudi 17 décembre 2020
Statut
Membre
Dernière intervention
17 octobre 2021
-
15 oct. 2021 à 18:15
yg_be Messages postés 22708 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 avril 2024 - 18 oct. 2021 à 08:21
yg_be Messages postés 22708 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 avril 2024 - 18 oct. 2021 à 08:21
A voir également:
- Php qui fait des calculs faux
- Easy php - Télécharger - Divers Web & Internet
- Citez un des logiciels lui permettant de faire des calculs sur des tableaux de nombres (tableur). - Forum Windev
- Rolland souhaite calculer le montant total des ventes de son magasin. le fichier contient, pour chaque produit, la quantité vendue et le prix unitaire. calculez le montant total des ventes. ✓ - Forum Excel
- Php?id=1 - Forum PHP
- Barbara veut calculer automatiquement son budget dans un tableau. citez un des logiciels lui permettant de faire des calculs sur des tableaux de nombres (tableur). - Forum Excel
7 réponses
jordane45
Messages postés
38139
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
20 avril 2024
4 649
15 oct. 2021 à 18:34
15 oct. 2021 à 18:34
Bonjour,
Déjà, force les valeurs en FLOAT
https://www.php.net/manual/fr/function.floatval.php
Et fais un var_dump de ta variable $donnees pour voir exactement ce qu'elle contient. (et montres le nous)
Déjà, force les valeurs en FLOAT
https://www.php.net/manual/fr/function.floatval.php
Et fais un var_dump de ta variable $donnees pour voir exactement ce qu'elle contient. (et montres le nous)
Whismeril
Messages postés
19025
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
19 avril 2024
929
16 oct. 2021 à 06:31
16 oct. 2021 à 06:31
Bonjour à tous les 2
@julienvo, tu peux aller faire un tour sur cette discussion
https://forums.commentcamarche.net/forum/affich-35846831-erreur-de-calcul#3
J'ai commencé par une vulgarisation que Dalfab a complétée. Reivax lui a parlé d'une solution propre à Python, je ne sais pas s'il y a un équivalent en PHP.
@julienvo, tu peux aller faire un tour sur cette discussion
https://forums.commentcamarche.net/forum/affich-35846831-erreur-de-calcul#3
J'ai commencé par une vulgarisation que Dalfab a complétée. Reivax lui a parlé d'une solution propre à Python, je ne sais pas s'il y a un équivalent en PHP.
jordane45
Messages postés
38139
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
20 avril 2024
4 649
16 oct. 2021 à 10:35
16 oct. 2021 à 10:35
Oui je confirme, c'est lié à la précision de la décimal...
Une solution pour contourner le souci ( à conditions que les nombres n'aient, au maximum, que deux chiffres après la virgules, est de les multiplier par 100 puis de diviser la somme par 100 )
par exemple
Une solution pour contourner le souci ( à conditions que les nombres n'aient, au maximum, que deux chiffres après la virgules, est de les multiplier par 100 puis de diviser la somme par 100 )
par exemple
$a = 688.16 *100; $b = 275 *100; $c = 413.16 *100; echo ($a - $b - $c)/100;
julienvo
Messages postés
5
Date d'inscription
jeudi 17 décembre 2020
Statut
Membre
Dernière intervention
17 octobre 2021
16 oct. 2021 à 19:21
16 oct. 2021 à 19:21
Bonjour,
merci pour votre aide.
pour répondre dans l'ordre, voici ce que retourne var_dump();
Si je change ma bdd en float, c'est pareil, même résultat
Ensuite, j'ai essayer la technique de multiplier puis diviser par 100, je comprend pas vraiment le but, mais ça change rien
Sinon j'ai entre temps modifier les formatage de la bdd et j'ai fait des essai, je pense que le problème vient de la.
j'ai mis les valeur de la table sur FLOAT 10,0 et le problème à disparu, je l'ai remis à 10,2 et il n'ai pas réapparu, car les chiffres après la virgule on disparu, donc le problème peut être résolu en cherchant par la?
merci pour votre aide.
pour répondre dans l'ordre, voici ce que retourne var_dump();
var_dump($TOTAL);
var_dump($montant_premier_payement);
var_dump($montant_second_payement);
var_dump($montant_troisieme_payement);
string(6) "688.16"
string(6) "275.00"
string(6) "413.16"
string(4) "0.00"
Si je change ma bdd en float, c'est pareil, même résultat
Ensuite, j'ai essayer la technique de multiplier puis diviser par 100, je comprend pas vraiment le but, mais ça change rien
$TOTAL = $donnees['TOTAL']*100/100;
$montant_premier_payement = $donnees['montant_premier_payement']*100/100;
$montant_second_payement = $donnees['montant_second_payement']*100/100;
$montant_troisieme_payement = $donnees['montant_troisieme_payement']*100/100;
Sinon j'ai entre temps modifier les formatage de la bdd et j'ai fait des essai, je pense que le problème vient de la.
j'ai mis les valeur de la table sur FLOAT 10,0 et le problème à disparu, je l'ai remis à 10,2 et il n'ai pas réapparu, car les chiffres après la virgule on disparu, donc le problème peut être résolu en cherchant par la?
jordane45
Messages postés
38139
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
20 avril 2024
4 649
16 oct. 2021 à 20:12
16 oct. 2021 à 20:12
par contre.. il ne faut pas diviser chaque chiffre ... mais le calcul total
julienvo
Messages postés
5
Date d'inscription
jeudi 17 décembre 2020
Statut
Membre
Dernière intervention
17 octobre 2021
17 oct. 2021 à 09:45
17 oct. 2021 à 09:45
ok, mais je comprend quand même pas le but, ça fait un peut bricolage et j’ai peur de m’embrouiller, en enregistrant une valeur qui à été multiplié, la page de code est très grande, et j'utilise cette base sur plusieurs page.
Si il y à une autre solution, et je suis sur que oui, je suis preneur.
Le problème c'est que les valeurs sont affiché en string et non en number, il y à pas une fonction qui force l'enregistrement en number?
J'utilise des . et pas des virgule pour l'enregistrement, c'est peut-être ça?
Si il y à une autre solution, et je suis sur que oui, je suis preneur.
Le problème c'est que les valeurs sont affiché en string et non en number, il y à pas une fonction qui force l'enregistrement en number?
J'utilise des . et pas des virgule pour l'enregistrement, c'est peut-être ça?
jordane45
Messages postés
38139
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
20 avril 2024
4 649
17 oct. 2021 à 09:56
17 oct. 2021 à 09:56
Si tes nombres ont (au maximum) deux chiffres après la virgule, en les multipliant par 100 ça permet de virtuellement les retirer.
Ensuite, tu divises par 100 le total pour remettre la décimal.... c'est des maths .. rien de plus..
Ensuite, tu divises par 100 le total pour remettre la décimal.... c'est des maths .. rien de plus..
julienvo
Messages postés
5
Date d'inscription
jeudi 17 décembre 2020
Statut
Membre
Dernière intervention
17 octobre 2021
>
jordane45
Messages postés
38139
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
20 avril 2024
17 oct. 2021 à 14:02
17 oct. 2021 à 14:02
ok, je comprend mieux , donc le problème c'est qu'il y avait trop de chiffre après la virgule d'après toi?
Ce que je comprend pas, c'est qu'ils été enregistré dans ma bdd en DECIMAL(10,2) ce qui veut dire un nombre entier de 10 chiffres maximum, avec une virgule et puis deux chiffres, donc si ce que tu dit est vrais, ça veut dire pa rexemple, que 688.16 en fait c'est ce qui est affiché, mais ce qui est enregistré c'est 688.16526523525626525225552 ou un truc comme ça.
Ce que je comprend pas, c'est qu'ils été enregistré dans ma bdd en DECIMAL(10,2) ce qui veut dire un nombre entier de 10 chiffres maximum, avec une virgule et puis deux chiffres, donc si ce que tu dit est vrais, ça veut dire pa rexemple, que 688.16 en fait c'est ce qui est affiché, mais ce qui est enregistré c'est 688.16526523525626525225552 ou un truc comme ça.
yg_be
Messages postés
22708
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
20 avril 2024
1 474
>
julienvo
Messages postés
5
Date d'inscription
jeudi 17 décembre 2020
Statut
Membre
Dernière intervention
17 octobre 2021
18 oct. 2021 à 08:21
18 oct. 2021 à 08:21
dans ta base de données, c'est bien enregistré comme 688.16.
par contre, PHP va peut-être le transformer plutôt en 688.16000000000001 ou 688.159999999999999.
en effet, PHP ne connait pas ce concept DECIMAL(10,2).
comme tu sais que ce sont des nombres décimaux à deux chiffres après la virgule, le plus prudent, c'est de multiplier ces nombres par 100, et que PHP les traite comme des entiers.
cela élimine les problèmes d'arrondi.
par contre, PHP va peut-être le transformer plutôt en 688.16000000000001 ou 688.159999999999999.
en effet, PHP ne connait pas ce concept DECIMAL(10,2).
comme tu sais que ce sont des nombres décimaux à deux chiffres après la virgule, le plus prudent, c'est de multiplier ces nombres par 100, et que PHP les traite comme des entiers.
cela élimine les problèmes d'arrondi.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
yg_be
Messages postés
22708
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
20 avril 2024
1 474
17 oct. 2021 à 11:05
17 oct. 2021 à 11:05
bonjour,
je ferais:
je ferais:
$solde_restant = round($TOTAL-$montant_premier_payement-$montant_second_payement-$montant_troisieme_payement , 2);
julienvo
Messages postés
5
Date d'inscription
jeudi 17 décembre 2020
Statut
Membre
Dernière intervention
17 octobre 2021
17 oct. 2021 à 14:13
17 oct. 2021 à 14:13
Merci pour ton idée, comme je l'ai dit avant, j'utilise ses donnée dans plusieurs page, je pense que la piste est bonne, mais qu'il fraudais enregistrer ça dans la bdd par exempleou bien de sortire les donnée de la bdd comme ca
$TOTAL = $donnees['TOTAL']; round($TOTAL, 2);
$TOTAL = $donnees['TOTAL']; round($TOTAL, 2);
Whismeril
Messages postés
19025
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
19 avril 2024
929
18 oct. 2021 à 06:28
18 oct. 2021 à 06:28
Bonjour
je pense que tu n'as pas compris le fond du problème.
Dans ton calcul, simple au demeurant, il y a au moins un nombre que l'ordinateur ne peut pas représenter. Que ce soit un des nombres d'entrée, un résultat intermédiaire ou le résultat final, peu importe.
Du coup ce nombre est "arrondi" au nombre le plus proche que l'ordinateur peut représenter. A 5E-14 près c'est pas la mort quand même.
Donc arrondir le résultat à la fin est un artifice. Stocker des arrondis dans ta base de données va à l'encontre de la précision des tes futurs calculs car tu ajoutes un biais à un résultat déjà biaisé.
La meilleure solution (informatiquement parlant) est celle proposée par Jordane.
Supposons que tes données soient de l'argent.
Si tu calcules tout en centimes (en multipliant par 100 les entrées) , ça devient des nombres entiers. Et contrairement au nombres à virgules, les nombres entiers sont tous représentables pour l'ordinateur (dans la limites du types, par exemple en C# un entier simple va de -2 147 483 648 à +2 147 483 647)
Donc jusqu'à la dernière étape ton calcul est 100% juste. Et la division par 100 d'un nombre entier (pour repasser en euros), normalement ne pose pas de problème d'imprécision.
je pense que tu n'as pas compris le fond du problème.
Dans ton calcul, simple au demeurant, il y a au moins un nombre que l'ordinateur ne peut pas représenter. Que ce soit un des nombres d'entrée, un résultat intermédiaire ou le résultat final, peu importe.
Du coup ce nombre est "arrondi" au nombre le plus proche que l'ordinateur peut représenter. A 5E-14 près c'est pas la mort quand même.
Donc arrondir le résultat à la fin est un artifice. Stocker des arrondis dans ta base de données va à l'encontre de la précision des tes futurs calculs car tu ajoutes un biais à un résultat déjà biaisé.
La meilleure solution (informatiquement parlant) est celle proposée par Jordane.
Supposons que tes données soient de l'argent.
Si tu calcules tout en centimes (en multipliant par 100 les entrées) , ça devient des nombres entiers. Et contrairement au nombres à virgules, les nombres entiers sont tous représentables pour l'ordinateur (dans la limites du types, par exemple en C# un entier simple va de -2 147 483 648 à +2 147 483 647)
Donc jusqu'à la dernière étape ton calcul est 100% juste. Et la division par 100 d'un nombre entier (pour repasser en euros), normalement ne pose pas de problème d'imprécision.