|
| Accueil → WINDEV 2025 → arrondi monétaire VS arrondi numérique (je ne comprends plus rien) |
| arrondi monétaire VS arrondi numérique (je ne comprends plus rien) |
| Débuté par AlexisPERR, 20 mai 2025 14:56 - 7 réponses |
| |
| | | |
|
| |
Membre enregistré 133 messages |
|
| Posté le 20 mai 2025 - 14:56 |
Bon je pensais avoir tout compris sur les arrondis, mais WinDEV arrive encore à me surprendre.
Examinons l'égalité mathématiquement exacte 1,583333 * 0,9 = 1,4249997
Le résultat 1,4249997 ayant 7 décimales; il ne tiendra pas dans un numérique ou monétaire, qui sont limités à 6 par défaut.
Que ce passe-t-il si l'on stocke cette valeur dans une variable ?
Faisons le test ensemble.
monNumérique1 is numeric = 1,4249997 monMonétaire1 is currency = 1,4249997
Trace(monNumérique1) donne 1,424999 Trace(monMonétaire1) donne 1,425
Ca alors, une première différence inattendue. Mais peut-être est-ce du au nombres entré tel quel, traité par le compilateur comme des réels. Forçont le type en mettant 0m ou 0n devant.
monNumérique2 is numeric = 0m1.4249997 monMonétaire2 is currency = 0m1.4249997
Trace(monNumérique2) donne 1,424999 Trace(monMonétaire2) donne 1,424999
monNumérique3 is numeric = 0n1.4249997 monMonétaire3 is currency = 0n1.4249997
Trace(monNumérique3) donne 1,424999 Trace(monMonétaire3) donne 1,424999
Ah, là cela donne bien la même chose. On voit que le nombre a été tronqué à 6 chiffres, le 0,0000007 est perdu. Si la règle usuelle d'arrondi avait été suivie, alors cela aurait du donner 1,425000 (de 5 à 9 on arrondi au chiffre supérieur).
Mais maintenant que se passe-t-il si l'on écrit 1,583333 * 0,9 au lieu de 1,4249997 ? Certainement cela ne doit rien changer ?
monNumérique4 is numeric = 0n1.583333 * 0n0.9 monMonétaire4 is currency = 0n1.583333 * 0n0.9
Trace(monNumérique4) donne 1,424999 Trace(monMonétaire4) donne 1,424999
monNumérique5 is numeric = 0m1.583333 * 0m0.9 monMonétaire5 is currency = 0m1.583333 * 0m0.9
Trace(monNumérique5) donne 1,425 Trace(monMonétaire5) donne 1,425
Patatra. Le calcul fait sur des scalaires numériques est différent sur les scalaires monétaires !
En d'autres termes,
0m1.583333 * 0m0.9 = 1,425
0n1.583333 * 0n0.9 = 1,424999
0m1.4249997 = 1,424999 0n1.4249997 = 1,424999
Je ne pense pas que cela soit normal, qu'en pensez-vous ? |
| |
| |
| | | |
|
| | |
| |
Membre enregistré 1 009 messages |
|
| Posté le 20 mai 2025 - 15:22 |
| |
| |
| | | |
|
| | |
| |
Membre enregistré 133 messages |
|
| Posté le 20 mai 2025 - 17:33 |
> Non essayé, mais le souci n'est-il pas dû au trace :
intéressant, mais non. |
| |
| |
| | | |
|
| | |
| |
Membre enregistré 133 messages |
|
| Posté le 22 mai 2025 - 11:55 |
pour être un peu plus clair, les numériques ne se comportent pas comme les monétaires (le numérique tronque, alors que le monétaire arrondi)
La preuve avec ce code, on fait le même calcul avec 3 variables numériques, puis 3 variables monétaires
nn1,nn2,nn3 is numeric nn1 = 1.583333 nn2 = 0.9 nn3 = nn1 * nn2
mm1,mm2,mm3 is currency mm1 = 1.583333 mm2 = 0.9 mm3 = mm1 * mm2
Et bien nn3 vaut 1,424999 alors que mm3 vaut 1,425000
Par comparaison avec CSHARP, le type float qui a 7 chiffres significatifs, on a le comportement suivant :
PUBLIC static string gcs_Test_Compare_Numeric_Currency() {
string sResult; float mm1,mm2,mm3;
mm1 = 1.583333F; mm2 = 0.9F; mm3 = mm1 * mm2;
sResult = mm3.ToString();
RETURN sResult;
}
renvoie 1.425 comme les monétaires WinDEV, il arrondi.
Je trouve donc le comportement du type numeric WinDEV assez suspect. Qu'en pensez-vous ? |
| |
| |
| | | |
|
| | |
| |
Membre enregistré 21 messages |
|
| Posté le 22 mai 2025 - 13:43 |
Bonjour,
nn1,nn2,nn3 is numeric (*) nn1 = 1.583333 nn2 = 0.9 nn3 = nn1 * nn2
Trace(nn3)
Bien cordialement, |
| |
| |
| | | |
|
| | |
| |
Membre enregistré 133 messages |
|
| Posté le 22 mai 2025 - 16:36 |
NN12 a écrit : > nn1,nn2,nn3 is numeric (*)
Tu n'as pas compris le sujet du topique. Le sujet du topique est que le type numérique, en dépassement de capacité, fait une troncature, alors que le type monétaire fait un arrondi. En mettant (*) tu demandes à WinDEV de déplacer sa précision automatiquement, mais le problème de dépassement de capacité se produira pareillement (par exemple sur 5/3).
Le sujet du topique est que un calcul fait en numérique rendra un résultat différent que le même calcul fait en monétaire, alors que l'on s'attendrait à ce que ces deux types résolvent leur dépassement de la même façon.
C'est à mon avis un bug de WinDEV, qui date depuis si longtemps, qu'il ne le corrigeront jamais de peur de planter tous les projets écrits sur cette erreur... |
| |
| |
| | | |
|
| | |
| |
Membre enregistré 21 messages |
|
| Posté le 22 mai 2025 - 16:55 |
Bonjour, Si tu penses que c'est un bug de la part de PCSoft, je t'invite à leur envoyer un mail au support gratuit. Ils te répondront plus en détails que nous, qui sommes des développeurs de leur produit. Bien cordialement, NN12 |
| |
| |
| | | |
|
| | |
| |
Membre enregistré 133 messages |
|
| Posté le 05 juin 2025 - 19:27 |
Bon j'ai avancé un peu sur ce problème. Il ne faut pas utiliser Trace come l'a dit @Cédric_34. Ni même le débuggeur pas à pas, les nombres affichés ne sont pas les vraies valeurs manipulées en interne. Il faut utiliser un champ de saisie avec un masque d'affichage ridiculement grand, par exemple 9.999999999999999999999999999999999999999999999999999999999999999999999
Voilà ce que cela donne si l'on range 0,9 dans ce champ :
0,900000000000000022204460492503130808472633361816406250000000000000000
Que l'on mette 0,9 à la main dans le champ de saisie, ou bien par affectation d'un real, currency ou numeric, le champ en sortie affiche systématiquement cette valeur approximative de 0,9
Voilà ce que cela donne si l'on range 1,583333 dans ce champ :
1,583333000000000101437080957111902534961700439453125000000000000000000
La première incohérence apparait lorsque l'on range dans ce champ non pas la valeur 1,583333, mais la valeur en numeric 1583333 / 1000000 Le champ affiche alors une valeur différente. Pour être plus précis,
1583333 / 1000000 0m1583333 / 0m1000000 0n1583333 / 0n1000000
donnent respectivement
1,583333000000000101437080957111902534961700439453125000000000000000000 1,583333000000000101437080957111902534961700439453125000000000000000000 1,583333000000000323481685882143210619688034057617187500000000000000000
On voit que la divergence apparait lorsque l'on demande au compilateur de faire le calcul entre deux nombres typés numeric. MAIS cette divergence n'a pas lieu si le calcul est fait non pas à la compilation, mais à l'exécution
nn1,nn2,nn3 is numeric nn1 = 0n1583333 / 0n1000000 nn2 = 0n9 / 0n10 nn3 = nn1 * nn2 SAI_NUMERICC = nn3
1,583333000000000101437080957111902534961700439453125000000000000000000
Donc vous allez me dire, évitons les calculs à la compilation, et faisons plutôt les calculs à l'exécution dans des variables bien typées ?
Oui mais non, car à l'exécution j'obtiens un écart significatif entre currency et numeric
1.583333 * 0.9 donne respectivement en real, currency, et numeric
1,424999700000000091293372861400712281465530395507812500000000000000000 1,425000000000000044408920985006261616945266723632812500000000000000000 1,424998999999999904630954006279353052377700805664062500000000000000000
En arrondissant à 6 chiffres, cela va donner
1,425000 1,425000 1,424999
Soit une différence de 0,000001, entre le calcul fait en real ou currency, et le calcul fait en numérique. C'est un bug assez énorme si on réfléchit bien. Cela ne vient pas du fait que numeric fait une troncature comme je l'avait pensé au début, il fait bien un Arrondi au plus proche, mais sur une base complètement fausse.
Je rappelle que le résultat de 1.583333 * 0.9 est un résultat exact qui vaut 1.4249997
Donc l'erreur faite en real et currency sera de +0,0000003 alors que l'erreur faite en numeric sera de -0,0000007 soit plus du double ! |
| |
| |
| | | |
|
| | | | |
| | |
|