Comparaison tuple

Le problème exposé dans ce sujet a été résolu.

Hello,

J'ai une question par rapport à la comparaison de tuple avec Python, car je n'ai pas le même comportement avec l'interpréteur et avec un code exécuté. En effet, je souhaite mettre en avant l'utilisation des fonctions poly de turtle et pour ce faire, je veux comparer le premier point avec le dernier pour savoir si nous ne sommes pas revenus au point de départ. Or, il se trouve qu'à chaque fois la comparaison != retourne True, même si le point d'arrivée est identique au point de départ. J'ai essayé en changeant de position de départ ainsi que la forme de la figure, mais ça ne change pas et je ne comprends pas ce qui ne va pas :

Avec la console :

1
2
3
4
(-0.00, 0.00) == (0.00, 0.00)
>> True
(-0.00, 0.00) != (0.00, 0.00)
>> False

Avec le code (cf. notre_end_fill) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import turtle

def notre_begin_fill():
    turtle.begin_fill()
    turtle.begin_poly()

def notre_end_fill():
    turtle.end_poly()
    poly = turtle.get_poly()
    if poly[0] != poly[-1]:  #Devrait être False
        print(poly)  #Affiche ((0.00,0.00), (90.00,0.00), (90.00,90.00), (0.00,90.00), (-0.00,0.00))
        print(poly[0])  #Affiche (0.00,0.00)
        print(poly[-1])  #Affiche (-0.00,0.00)
        turtle.goto(poly[0])
    turtle.end_fill()

if __name__ == "__main__":
    turtle.color("red", "green")
    notre_begin_fill()
    for i in range(4):
        turtle.forward(90)
        turtle.left(90)
    notre_end_fill()

Merci de votre aide !

EDIT : La version de Python utilisée est la 3.4.3

+0 -0

Sais-tu à quoi est dû ce -1.6532731788489267e-14 ? Une imprécision de turtle ?

Smokiev

Le problème de base des nombres flottants en informatique est qu'on ne peut pas en représenter certains. Par exemple pour nous humains, 1/3 n'est pas représentable de manière exacte (0.3 ? non. 0.333 ? non. 0.333333<1 milliard de 3> ? presque … mais non quand même). En plus de ça, il est possible que Python et/ou Turtle rajoute une couche d'imprécision.

Pour résoudre ton problème, il faut que tu calcule la différence entre tes nombres (ou vecteurs en l'occurence), et si cette différence est plus petite qu'un certain nombre X très petit, alors tu les considère égaux :

1
2
3
>>> EPSILON = 10**-10  # un nombre arbitrairement petit, a ajuster en fonction de tes besoins
>>> abs(poly[0]-poly[-1]) < EPSILON
True

(Puisqu'on est en python, tu peux surcharger les méthode __eq__ et __neq__ de turtle.Vect2D pour éviter cette méthode très verbeuse.)

Quelques ressources pour comprendre : un premier article plutôt lisible et un deuxième sympa aussi et un dernier qui rentre dans les détails.

De manière général, quand on compare des nombres flottant, quelque soit le langage, on ne teste jamais l'égalité directement.

Kje

Même si c'est toi qui définit les valeurs ?

Concrètement, dans ton cas précis : bosse avec des coordonnées entières et ton problème sera résolu.

nohar

Tu as raison, je vais utiliser round et ça fera l'affaire ici :)

Yep,

Mais ça retourne un flottant arrondi à un nombre de chiffres après la virgule choisi :

1
2
3
4
>>> round(0.99432656, 0)
1.0
>>> round(0.4444, 0)
0.0

Tandis que int arrondit toujours à l'entier inférieur (enfin pour être exact : "For floating point numbers, this truncates towards zero.") :

1
2
3
4
>>> int(0.9999)
0
>>> int(0.4444)
0

Ce qui est donne moins de précision ici, c'est pourquoi je préfère utiliser round.

+0 -0

Ça restera des flottants. Les pixels de ton écran, c'est une valeur discrète, il n'y a aucune raison d'utiliser des flottants pour ça. Si ça te rassure d'utiliser round, utilise au moins int(round(...)).

+0 -0

Ça restera des flottants. Les pixels de ton écran, c'est une valeur discrète, il n'y a aucune raison d'utiliser des flottants pour ça. Si ça te rassure d'utiliser round, utilise au moins int(round(...)).

nohar

Oui c'est vrai, mais ici turtle nous fournit des points flottants (get_poly). Effectivement, je peux toujours convertir en entier après avoir arrondi avant de comparer les deux points, mais au final est-ce que ça change quelque chose vu que j'arrondirai à 0 chiffre après la virgule ? Donc l'utilisation de int n'est pas forcément nécessaire, mais peut-être qu'elle fait plus sens comme tu le dis.

+0 -0

l'utilisation de int n'est pas forcément nécessaire

On vient de passer une page à t'expliquer que l'égalité stricte entre flottants n'était pas fiable…

nohar

Oui, oui, ça j'ai bien compris ce que je veux dire c'est que l'utilisation de int n'est pas nécessaire si j'arrondis comme je l'ai dit plus haut avec round(x, 0), à moins que je fasse erreur et que la comparaison de deux flottants de la forme x.x0 et x.x0 (comme 0.0 et 0.0) après avoir arrondi n'est pas fiable (d'où ma question à Kje un peu plus haut dans la page)

+0 -0

De manière général, quand on compare des nombres flottant, quelque soit le langage, on ne teste jamais l'égalité directement.

Kje

Même si c'est toi qui définit les valeurs ?

Smokiev

Dans la plupart des cas, comparer des flottant fonctionnera comme tu t'y attend. Mais dans certains cas (et oui, même si cest toi qui défini les valeurs), ça peux ne pas marcher. Et c'est justement pour éviter ces cas qui sont dur à prédire (quand on lis le code) et surtout à débug-er qu'il vaut mieux éviter de faires des trucs dont on est pas sur et qui sont sources d'erreurs.

Sincèrement et d'expérience, prédire les cas où ça va marcher est trop compliqué et source d'erreur pour en valoir le coup. D'autant que c'est typiquement le genre de problème dépendant de la plateforme (les cas problématique ne seront pas forcément les mêmes sur ton PC et sur ceux de quelques-un d'autre).

Si turtle te fournit des float, fait des comparaisons en regardant la différence. Et fait le à chaque fois que tu dois comparer des float.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte