Python, virgule flottante, cos(pi)

Bonjour,
Quelqu’un peut-il m’éclairer sur la manière dont python calcule les sinus et cosinus, car je bloque sur :

In[1]:  from math import cos,sin,pi

In[2]:  sin(pi)
Out[2]: 1.2246063538223773e-16

In[3]:  cos(pi)
Out[3]: -1.0

In[4]:  cos(2*pi)
Out[4]: 1.0

In[5]:  sin(pi/2)
Out[5]: 1.0

Je comprends que la valeur en virgule flottante de pi, irrationnel, ne puisse pas être représentée en binaire. La valeur de sin(pi) est donc une valeur approchée de zéro.
Mais pourquoi les autres calculs [3],[4] et [5] renvoient-ils des valeurs, en virgule flottante, exactes ?

Merci d’avance !

Parce que ce sont des valeurs entières je suppose. Alors effectivement, avoir un chiffre après la virgule peut être étonnant. Sans doute pour préciser qu’on est sûr de cette valeur (très apprécié par les physiciens ce genre de détails)

Bonjour et merci de ta réponse.
Le résultat est un float :

In[5] : type(sin(pi/2))
Out[5]: float

donc 1.0 ne me dérange pas, mais est-ce une valeur entière ?
J’aurais plutôt pensé que ce résultat est arrondi, par exemple 0.99999xxxx… avec plus de décimales que ne peut gérer le type float d’où l’arrondi à 1.

Mais ce n’est qu’une supposition…

Non non, le résultat est bel et bien entier (un mathématicien me contredira peut-être).
Par contre, je ne sais pas pourquoi les développeurs python ont fait ce choix.

C’est très probablement le cas. Il faudrait se plonger dans la doc de python pour voir précisément comment c’est calculé, mais oui, dans le premier cas de ton exemple l’écart est trop important pour en faire un arrondi automatique alors que dans les autres si, mais c’est bien d’un arrondi qu’il s’agit.

De manière générale en informatique quand tu travail avec des flottants, il n’y a pas de valeur exacte et il faut traiter des intervalles (grosso modo il s’agit de l’imprécision que tu trouve acceptable). Si tu ne veux pas d’imprécision alors, il faut travailler avec des outils plus spécialisés (il y a des bibliothèques python faites pour ça par exemple). Ils gardent en interne leur propre représentation des flottants et n’utilisent pas (ou peu) les fonctions des CPU pour faire leur calcul (ils réimplémentent les opérations sur ces nombres).

@thuban > Oui en mathématiques c’est une valeur entière, mais pas en informatique :slightly_smiling: La gestion des nombres à virgule flotante est trèx complexe et par exemple, le modèle de ton procésseur va modifier le résultat d’une même opération (il paraît que les opération qui ont eu lieu avant modifient aussi les résultats).

[quote=“MisterFreez”]
@thuban > Oui en mathématiques c’est une valeur entière, mais pas en informatique :slightly_smiling: La gestion des nombres à virgule flotante est trèx complexe et par exemple, le modèle de ton procésseur va modifier le résultat d’une même opération (il paraît que les opération qui ont eu lieu avant modifient aussi les résultats).[/quote]
C’est noté :slightly_smiling: Je croyais bêtement qu’un ordinateur savait calculer. :stuck_out_tongue:

Merci beaucoup pour cette explication, c’est à peu près ce que j’imaginais sans réussir à le formuler !

Il est très probable que ici 1.0 résulte d’un arrondi qui tout bien. Ça coince avec pi/6:

[code]>>> sin(pi/2)-1
0.0

2*sin(pi/6)-1
-1.1102230246251565e-16

[/code]

La seule façon de ne plus avoir d’erreurs en flottant est de faire du calcul formel où tu conserves l’origine du réel et non sa valeur.

Par contre j’ai du mal à croire à un processeur qui rendrait un résultat dépendant des opérations précédemment effectuées, ce serait une aberration.

ok, merci , mais pas besoin de calcul formel !
Je me posais juste la question…

Oui c’est ce que j’entendais par outil adapté. C’est aussi ce que nous faisons quand on effectue un calcul impliquant des nombres irrationnels (ou même des décimaux). On remet au plus tard possible l’utilisation des valeurs numériques.

Il faudrait que je retrouve le lien, je me suis peut être trompé.
Mais tu peux vraiment avoir des comportements surprenant en fonction de l’ordre de tes expressions pour un CPU et un compilateur donné (mauvaises utilisation des FPU). Grosso modo selon l’ordre que tu donne à tes calculs, les valeurs seront représentés en double précision, en précision simple ou dans des précisions supérieur. C’est le même genre de problème qui fait qu’en informatique on préfère calculer 1456/100000000 que 14/10000000056.

En cherchant rapidement, on trouve ceci par exemple : network-theory.co.uk/docs/gc … ro_70.html

sinon avec sympy
In [6]: 2*sympy.sin(sympy.pi/6)-1
Out[6]: 0

le type est par contre sympy.core.numbers.Zero