Pour des valeurs entieres multiples de 13, TRUNC me renvoie la valeur inférieure.
Ex:
TRUNC(0.65/0.05) = 12
TRUNC(5.2/0.1) = 51
TRUNC(1.3/0.1) = 12
alors que
TRUNC(13) = 13...
superstition???? ou magie
Pour des valeurs entieres multiples de 13, TRUNC me renvoie la valeur inférieure.
Ex:
TRUNC(0.65/0.05) = 12
TRUNC(5.2/0.1) = 51
TRUNC(1.3/0.1) = 12
alors que
TRUNC(13) = 13...
superstition???? ou magie
C'est certainement un problème dû à la division (multiplication) réelle. Tu travaille avec des réels donc le calcul n'est qu'une succession d'arrondis. Le résultat obtenu pour 5.2 / 0.1 est peut-être 5.1999...e1. Donc quand tu tronques, tu retombes sur 51.
Pour bien faire, il faudrait peut-être faire un test sur la valeur obtenue, par exemple :
Donc tu introduis un nombre "limite" que tu considères comme négligeable dans tes calculs et si ton résultat + cette limite dépasse la dizaine alors c'est qu'il y'a eu une erreur d'arrondi. Normalement il devrait être de l'ordre de la précision de la mantisse, ce qui dépend de la plateforme, mais 1e-15 devrait être convenable.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 const limite = 0.001; ... res := 5.2 / 0.1; tronc := TRUNC(res); if TRUNC(res + limite) > tronc then tronc := tronc+1;
sur mon Turbo Pascal 7.01 téléchargé sur DVP, WriteLn(Trunc(5.2 / 0.1)) m'affiche bien 52 à l'écran .... sur quel compilateur travailles-tu ?
Donnez un poisson à un homme et il mangera pendant un jour... Apprenez-lui à pêcher et il s'assiéra dans une barque et boira de la bière toute la journée
Bonjour !
Par contre, Free Pascal 2.0.2 et Virtual Pascal 2.1 renvoient tous deux 51.
Règles du forum
Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
Mes tutoriels et sources Pascal
Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]
idem Free pascal 1.0.6 ça donne du 12 au lieu de 13 !
je pense que c'est vraiment un bug et même que c'est grave comme problème !
j'ai essayé avec Freepascal de mettre l option compatible avec TP 7.0 mais ça ne change rien : le resultat reste faux !
sinon ce n'est pas trop une fonction que j'utilise (je prefère quand cela est possible) utiliser INT mais quand même ça fait désordre !
Un bon exemple vaut mieux qu'une longue explication confuse...
Merci de vos réponses,
Le plus étonnant est que cela intervient seulement pour les multiples de 13. Donc le type REAL n y est pour rien ...C'est certainement un problème dû à la division (multiplication) réelle. Tu travaille avec des réels donc le calcul n'est qu'une succession d'arrondis. Le résultat obtenu pour 5.2 / 0.1 est peut-être 5.1999...e1. Donc quand tu tronques, tu retombes sur 51.
Quant à moi, j utilises le compilateur de VAX VMS.
salut,
ce qui est sûr est que les ordinateurs font le calcul avec une telle certitude variant en fonction de l'espace mémoire utilisé pour sauvegarder une valeure (le nbre des bits representant la valeur ) d'où une division comme celle ci 5.2/0.1 donne 51.9999999999... qui est pratiquement = 52. Dans ce niveau, le compilateur fait intervenir en appelant la fonction Trunc, y en a des compilaeteurs qui te donne 52 et d'autre qui donne 51 comme résultat.
Pour la remarque du l'entier 13 et ses multiple, bah je c pas exactement le truc, mais j'aimerai bien le savoir...
++
Bonjour,
Alors ceux qui donnent 52 font une erreur : TRUNC, c'est la partie entière d'un nombre, donc = 51 pour 51.9999999999Envoyé par Blue_Strike
Et les calculs sur des réels sont toujours approximatifs, le problème étant effectivement dû à la représentation de la valeur (qui change, en particulier avec les REAL des compilateurs.
Compilation sans erreur ne signifie pas programme sans erreur.
L'indentation n'a pas été imaginée pour faire beau, mais pour faciliter la lecture des programmes.
Il n'y a pas que la valeur 13 qui soit concernée !
N'oublions pas qu'il y a une différence fondamentale entre :
et
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 Begin WriteLn(Trunc(4.0/0.4)); End.
Dans le premier cas, c'est le compilateur qui effectue le calcul (troncature comprise) et qui code le résultat en dur dans l'exécutable; dans le second cas, la fonction Trunc de la RTL est réellement appelée lors de l'exécution. Vérifié dans les outputs Assembleur générés lors de la compilation.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 Var a, b : Real; // Ou tout autre type de réel Begin a := 4.0; b := 0.4; WriteLn(Trunc(a/b)); End.
J'ai fait une petite expérience avec Virtual Pascal 2.1 :
- Dans le 1er cas : résultat = 10
- Dans le 2ème cas avec le type Real : résultat = 9
- Dans le 2ème cas avec le type Double : résultat = 9
- Dans le 2ème cas avec le type Extended : résultat = 10.
Règles du forum
Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
Mes tutoriels et sources Pascal
Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]
Donc c'est bien une erreur d'approximation dûe à la taille de la mantisse ?
La solution que je proposait est donc valide il me semble, même si c'est plus ou moins du bidouillage...
Bonjour,
Oui, c'es du bidouillage, mais on n'y échappe pas, quel que soit le langage utilisé.
Une alternative serait d'utiliser des réels de précision quelconque, mais de toute manière ce ne serait que décaler le problème, vu que, bien entendu, on ne peut utiliser une précision infinie, qui serait nécessaire pour représenter exactement n'importe quelle valeur.
Et le prix serait le temps de calcul, puisque cela interdirait d'utiliser l'unité de calculs flottants du processeur. De quoi avoir besoin d'une cafetière en attendant la fin d'un calcul.
Compilation sans erreur ne signifie pas programme sans erreur.
L'indentation n'a pas été imaginée pour faire beau, mais pour faciliter la lecture des programmes.
personnellemnent ça me gêne quand même..Oui, c'es du bidouillage, mais on n'y échappe pas, quel que soit le langage utilisé.
en fonction du compilateur on a 12 ou 13
en fonction de déclaré en variable ou directement en calcul dans le write
je pense que le systeme d exploitation doit aussi jouer si on est sur 16 32 ou 64 bits ?
donc je m'imagine je fais un programme et si j'ai 13 ma barriière se baisse quand le train passe sinon je la laisse ouverte.
je change de compilateur ou si je recompile pour une raison ou pour une autre et ma barriere ne se baisse plus... parce que j'ai 12.
programmer n'est pas bidouiller tout de même... ??
sur un code de 100 lignes on peut s'en apercevoir mais si mon programme fait 20000 lignes ... et si en interne j'ai de temps en temps 12.000000001 ou 11.999999999 difficile quand même à deceler...
Un bon exemple vaut mieux qu'une longue explication confuse...
Bonjour,
Quand on travaille avec les réels, il faut fraire très attention, et le résultat des calculs dépend de la représentation en mémoire, soit en natif du processeur, soit autre.Envoyé par JoseF
Et ce que tu obtiens avec write est une approximation de plus par rapport à la valeur effectivement stockée (arrondi dû aux nombres de chiffres que tu demandes en affichage).
Le seul moyen de "contourner" ce problème, est d'accepter le test pour vrai si si les valeurs testées sont suffisamment proches ("suffisamment proche" reste à définir pour chacun, sachant que ça va dépendre de l'ordre de grandeur de la valeur, dû à la précision limitée des réels).
Si tout ça te pose problème, n'utilise que des entiers (pas toujours possible, n'est-ce pas ?), ou fait toi une librairie de calcul des réels en très haute précision (ce qui n'est que reculer pour mieux sauter, la précision ne pouvant évidemment pas être infinie), ou arrête de programmer : c'est un problème incontournable sans bricoler un peu.
Compilation sans erreur ne signifie pas programme sans erreur.
L'indentation n'a pas été imaginée pour faire beau, mais pour faciliter la lecture des programmes.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager