Erreur calcul d'entier
Résolu/Fermé
A voir également:
- Erreur calcul d'entier
- Erreur 0x80070643 - Accueil - Windows
- Calcul moyenne excel - Guide
- Erreur 0x80070643 Windows 10 : comment résoudre le problème de la mise à jour KB5001716 - Accueil - Windows
- Erreur 1001 outlook - Accueil - Bureautique
- Calcul charpente bois gratuit - Télécharger - Architecture & Déco
11 réponses
yg_be
Messages postés
23352
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
27 novembre 2024
Ambassadeur
1 554
21 avril 2021 à 23:07
21 avril 2021 à 23:07
bonjour,
il n'est en effet pas toujours simple d'écrire un programme donnant le résultat espéré.
et il existe de nombreux programmes, comme le tien, donnant des résultats non fiables.
si tu sais que le résultat de la division est "mathématiquement" entier (comme dans tous les exemples que tu donnes, alors fais ainsi:
Python ne travaille pas naturellement en base décimale. Quand tu lui fournis un nombre tel que 0.6, il va mémoriser, à sa manière, un nombre le plus proche possible de 0.6. Un peu comme tu mémoriserais un tiers : 0.3333333333
Ainsi, dès que tu fournis un nombre décimal non entier à Python, tu dois être conscient que ce nombre mémorisé peut être légèrement différent. C'est au moment de faire cela que tu introduis une erreur, amplifiée par les opérations choisies ensuite.
Tu peux facilement éviter cela en n'utilisant que des entiers: 600/5, 60/5, 600/5, 700/5.
Ou en utilisant des fractions, ainsi:
il n'est en effet pas toujours simple d'écrire un programme donnant le résultat espéré.
et il existe de nombreux programmes, comme le tien, donnant des résultats non fiables.
si tu sais que le résultat de la division est "mathématiquement" entier (comme dans tous les exemples que tu donnes, alors fais ainsi:
def calc(x,y): print(x,y,round(x/y)) calc(0.6,0.005) calc(0.6,0.05) calc(60,0.5) calc(0.7,0.005)
Python ne travaille pas naturellement en base décimale. Quand tu lui fournis un nombre tel que 0.6, il va mémoriser, à sa manière, un nombre le plus proche possible de 0.6. Un peu comme tu mémoriserais un tiers : 0.3333333333
Ainsi, dès que tu fournis un nombre décimal non entier à Python, tu dois être conscient que ce nombre mémorisé peut être légèrement différent. C'est au moment de faire cela que tu introduis une erreur, amplifiée par les opérations choisies ensuite.
Tu peux facilement éviter cela en n'utilisant que des entiers: 600/5, 60/5, 600/5, 700/5.
Ou en utilisant des fractions, ainsi:
def calc2(x,y): print(x,y,int((x[0]*y[1])/(x[1]*y[0]))) calc2([6,10],[5,1000]) calc2([6,10],[5,100]) calc2([60,1],[5,10]) calc2([7,10],[5,1000])
Phil_1857
Messages postés
1872
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
28 février 2024
168
21 avril 2021 à 17:16
21 avril 2021 à 17:16
Bonjour,
/ est le symbole de la division
// est le symbole de la division entière
0.6//0.005=119.0 reste 0.005
/ est le symbole de la division
// est le symbole de la division entière
0.6//0.005=119.0 reste 0.005
Bonjour,
Hé non, la division entière de 0.06 par 0.005 = 120, reste 0 normalement.
Donc je comprends pas pourquoi python sort 119 dans ce cas précis.
D'ailleurs si je pars de 0.7 et pas 0.6, j'ai bien :
0.07//0.005 = 140 et pas 139 (et 0.07%0.005 = 0)
Et pour en revenir au cas initial, des cas équivalents mathématiquement :
6//0.05=119
60//0.5=120
Donc ça ressemble à des problèmes de précision numérique mais comme dit plus haut, si je fais int(0.6/0.05) je devrais avoir la même erreur dans ce cas (puisque ça revient à faire la division entière) alors que non.
Hé non, la division entière de 0.06 par 0.005 = 120, reste 0 normalement.
Donc je comprends pas pourquoi python sort 119 dans ce cas précis.
D'ailleurs si je pars de 0.7 et pas 0.6, j'ai bien :
0.07//0.005 = 140 et pas 139 (et 0.07%0.005 = 0)
Et pour en revenir au cas initial, des cas équivalents mathématiquement :
6//0.05=119
60//0.5=120
Donc ça ressemble à des problèmes de précision numérique mais comme dit plus haut, si je fais int(0.6/0.05) je devrais avoir la même erreur dans ce cas (puisque ça revient à faire la division entière) alors que non.
Phil_1857
Messages postés
1872
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
28 février 2024
168
21 avril 2021 à 20:46
21 avril 2021 à 20:46
ha ?
bizarre...
moi, j'ai écrit ce code:
et à l'exécution, ca donne ça:
bizarre...
moi, j'ai écrit ce code:
print('\n0.6//0.005={} reste {:.5f}'.format(0.6//0.005, 0.6%0.005))
et à l'exécution, ca donne ça:
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Oui justement, c'est ce que sort le code, mais mathématique c'est faux. Et comme expliqué plus haut, si on écrit la fraction 60//0.5 (qui est exactement la même chose) le résultat est maintenant bien 120.
Et si vous faites 0.7//0.005 là vous obtenez bien 140 et non pas 139. Donc en résumé le résultat de cette opération n'est pas fiable.
Et si vous faites 0.7//0.005 là vous obtenez bien 140 et non pas 139. Donc en résumé le résultat de cette opération n'est pas fiable.
Phil_1857
Messages postés
1872
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
28 février 2024
168
22 avril 2021 à 12:27
22 avril 2021 à 12:27
Bonjour yg_be,
Effectivement, c'est bizarre quand même !
En Python, //, c'est la division entière, ou division euclidienne
Or, dans mon code posté ci-dessus, il accepte des float comme arguments
Quand j'essaye de faire ça sur ma calculatrice (j'ai un bouton division entière),
j'ai bien évidemment une erreur : Error Int, ce qui est logique, elle attend des entiers
Et quand on fait 30//4, on obtiens 7 reste 2 ...
Effectivement, c'est bizarre quand même !
En Python, //, c'est la division entière, ou division euclidienne
Or, dans mon code posté ci-dessus, il accepte des float comme arguments
Quand j'essaye de faire ça sur ma calculatrice (j'ai un bouton division entière),
j'ai bien évidemment une erreur : Error Int, ce qui est logique, elle attend des entiers
Et quand on fait 30//4, on obtiens 7 reste 2 ...
Bonjour yg_be,
Oui j'ai l'habitude de gérer les problèmes de précision numérique. Mon problème là c'est que ça ne semble pas être le cas car quand on fait int(0.6/0.005) on obtient bien 120 et pas 119 alors que si c'était un problème de précision numérique on devrait obtenir 119 (puisque int revient à prendre la partie entière).
C'est même encore pire que ça, puisque :
0.6//0.005=119 (faux)
int(0.6/0.005)=120 (correct)
0.6//0.05=11 (faux)
int(0.6/0.05)=11 (faux aussi)
Donc ça marche un peu quand ça veut quoi, même avec int. Et si je repars sur le cas initial:
60//0.5=120
60.0//0.5=120
6//0.05=119
C'est quand même surprenant cette histoire !
Oui j'ai l'habitude de gérer les problèmes de précision numérique. Mon problème là c'est que ça ne semble pas être le cas car quand on fait int(0.6/0.005) on obtient bien 120 et pas 119 alors que si c'était un problème de précision numérique on devrait obtenir 119 (puisque int revient à prendre la partie entière).
C'est même encore pire que ça, puisque :
0.6//0.005=119 (faux)
int(0.6/0.005)=120 (correct)
0.6//0.05=11 (faux)
int(0.6/0.05)=11 (faux aussi)
Donc ça marche un peu quand ça veut quoi, même avec int. Et si je repars sur le cas initial:
60//0.5=120
60.0//0.5=120
6//0.05=119
C'est quand même surprenant cette histoire !
yg_be
Messages postés
23352
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
27 novembre 2024
1 554
22 avril 2021 à 22:36
22 avril 2021 à 22:36
tu n'as en rien tenu compte de ce que j'ai écris le 21 avril 2021 à 23:07.
si tu es satisfait d'être surpris, alors, surtout, ne change rien. comme tu l'observes, ton code n'est pas fiable.
si tu veux obtenir un résultat prévisible, alors, adapte ton code.
si tu n'as pas de question, peux-tu marquer la discussion comme résolue?
si tu es satisfait d'être surpris, alors, surtout, ne change rien. comme tu l'observes, ton code n'est pas fiable.
si tu veux obtenir un résultat prévisible, alors, adapte ton code.
si tu n'as pas de question, peux-tu marquer la discussion comme résolue?
Bonjour,
Non ça ne répond pas à la question initiale. Si tu es satisfait de répondre à côté alors ne change rien. Mais comme tu l'observes ça ne répond pas à la question. (Moi aussi je peux prendre un ton agressif).
Bref, je reformule : si c'est un problème de précision numérique, comme tu dis, alors cela signifie que lorsque python fait la division de 0.6 par 0.0005 il obtient quelque chose comme 119.999999999, par ex, ce qui ferait effectivement que dans ce cas en réalisant l'opération 0.6//0.0005 on obtient 119. Sauf que si c'était le cas, alors int(0.6/0.0005) devrait aussi donner 119, alors que ça donne bien 120.
J'aimerais donc comprendre quelle est la raison réelle qui fait que Python donne 119 dans un cas et 120 dans l'autre, puisque visiblement ce n'est pas un problème numérique. Ou alors si c'en est un, pourquoi il conduit à une erreur dans un cas et pas dans l'autre.
Quant au code que tu proposes, il fonctionne effectivement si on sait par avance écrire la variable en question sous forme de fraction, ce qui n'est pas mon cas puisque je cherche à découper en tranche un espace de taille quelconque à partir d'un pas de longueur donnée.
Non ça ne répond pas à la question initiale. Si tu es satisfait de répondre à côté alors ne change rien. Mais comme tu l'observes ça ne répond pas à la question. (Moi aussi je peux prendre un ton agressif).
Bref, je reformule : si c'est un problème de précision numérique, comme tu dis, alors cela signifie que lorsque python fait la division de 0.6 par 0.0005 il obtient quelque chose comme 119.999999999, par ex, ce qui ferait effectivement que dans ce cas en réalisant l'opération 0.6//0.0005 on obtient 119. Sauf que si c'était le cas, alors int(0.6/0.0005) devrait aussi donner 119, alors que ça donne bien 120.
J'aimerais donc comprendre quelle est la raison réelle qui fait que Python donne 119 dans un cas et 120 dans l'autre, puisque visiblement ce n'est pas un problème numérique. Ou alors si c'en est un, pourquoi il conduit à une erreur dans un cas et pas dans l'autre.
Quant au code que tu proposes, il fonctionne effectivement si on sait par avance écrire la variable en question sous forme de fraction, ce qui n'est pas mon cas puisque je cherche à découper en tranche un espace de taille quelconque à partir d'un pas de longueur donnée.
yg_be
Messages postés
23352
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
27 novembre 2024
1 554
23 avril 2021 à 09:27
23 avril 2021 à 09:27
et le premier code que je propose, il ne te donne pas le résultat attendu?
tu n'as pas expliqué le résultat attendu dans le cas où l'espace n'était pas un multiple du pas. par exemple si l'espace vaut 3 et le pas vaut 0.4.
si je comprends bien, tu t'étonnes que, pour certaines valeurs, int(x/y) soit parfois différent de x//y.
moi, je constate que, pour ces valeurs, la réponse étant indéterminée, Python, en utilisant deux algorithmes différents, arrive à deux résultats différents.
et je propose d'autres méthodes de calcul pour éviter une réponse indéterminée.
surtout, éviter comme la peste de tronquer une valeur indéterminée proche d'un entier.
tu n'as pas expliqué le résultat attendu dans le cas où l'espace n'était pas un multiple du pas. par exemple si l'espace vaut 3 et le pas vaut 0.4.
si je comprends bien, tu t'étonnes que, pour certaines valeurs, int(x/y) soit parfois différent de x//y.
moi, je constate que, pour ces valeurs, la réponse étant indéterminée, Python, en utilisant deux algorithmes différents, arrive à deux résultats différents.
et je propose d'autres méthodes de calcul pour éviter une réponse indéterminée.
surtout, éviter comme la peste de tronquer une valeur indéterminée proche d'un entier.
yg_be
Messages postés
23352
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
27 novembre 2024
Ambassadeur
1 554
23 avril 2021 à 09:37
23 avril 2021 à 09:37
Tu demandes deux choses: "Quelle en est la raison" et "cela pose des problèmes".
Cherches-tu une solution à ces problèmes, ou bien, ayant trouvé une solution, veux-tu comprendre "pourquoi"?
Cherches-tu une solution à ces problèmes, ou bien, ayant trouvé une solution, veux-tu comprendre "pourquoi"?
Les 2 mon capitaine :)
Je ne comprends effectivement pas pourquoi int(x/y) soit parfois différent de x//y. J'aurais aimé comprendre la raison de ce résultat différent (parce que fondamentalement, ces 2 opérations font la même chose, à savoir donner le résultat de la division entière et devrait donc générer les mêmes erreurs).
Mais je retiens le conseil sur le fait de ne pas tronquer mais plutôt d'arrondir, merci. Je vais qd même vérifier que le calcul avec round reste valable dans le cas où l'espace n'est pas un multiple du pas.
Je ne comprends effectivement pas pourquoi int(x/y) soit parfois différent de x//y. J'aurais aimé comprendre la raison de ce résultat différent (parce que fondamentalement, ces 2 opérations font la même chose, à savoir donner le résultat de la division entière et devrait donc générer les mêmes erreurs).
Mais je retiens le conseil sur le fait de ne pas tronquer mais plutôt d'arrondir, merci. Je vais qd même vérifier que le calcul avec round reste valable dans le cas où l'espace n'est pas un multiple du pas.
yg_be
Messages postés
23352
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
27 novembre 2024
1 554
23 avril 2021 à 09:59
23 avril 2021 à 09:59
tu n'as pas expliqué le résultat attendu dans le cas où l'espace n'était pas un multiple du pas. par exemple si l'espace vaut 3 et le pas vaut 0.4. la suggestion avec round() n'est certainement pas adéquate dans ce cas-là.
Impec
>
yg_be
Messages postés
23352
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
27 novembre 2024
23 avril 2021 à 10:03
23 avril 2021 à 10:03
Oui ça ne marche pas dans ce cas (puisqu'un arrondi supérieur rajoute un point en dehors de l'espace). Mais je vais procéder différemment, je vais plutôt déduire le pas du nombre de points que l'inverse, ça évitera d'être coincé par ces considérations. Je mets le problème comme résolu du coup.
En python,
Par exemple :
Donc si on veut utiliser une division euclidienne il faut l'effectuer sur des entiers, ce n'est pas une question de précision.
//est un opérateur sur des nombres entiers de tye (
int), on ne peut pas prévoir ce qu'il donne sur d'autres nombres mais on pourrais espérer que l'interpréteur lève une erreur en cas d'utilisation sur des types
float.
Par exemple :
>>> 0.6//0.005 119.0 >>> 600//5 120
Donc si on veut utiliser une division euclidienne il faut l'effectuer sur des entiers, ce n'est pas une question de précision.