Étant très inspiré par un récent journal, je me souviens de différences de comportements entre les langages de programmation.
J'ai moins de détails techniques croustillants à mentionner, mais pour ceux qui manipulent des chiffres et des lettres, ça peut être intéressant.
Supposons que l'on veuille arrondir une valeur. -0.5. Facile ? Et bien en fait, pas du tout !
round(-0.5) =
- Python: -1
- WolframAlpha: 0
- PHP: -1
- JavaScript: -0
- Matlab: -1
- Java: 0
Si l'on tient compte du zéro négatif de JS, on a 3 valeurs différentes, et aucune n'est aberrante vu qu'en fait, c'est très louche, la notion d'arrondi. Une petite recherche sur Wikipédia nous donne en fait cinq solutions d'arrondis pour lever l’ambiguïté ou diminuer les erreurs accumulées d'arrondis en arrondis. Plutôt que de se perdre dans les détails, on va regarder les arrondis uniquement dans le domaine de l'informatique :
- Arrondi vers moins l'infini
- Arrondi vers plus l'infini
- Arrondi vers zéro
- Arrondi au plus loin de zéro
- Arrondi au nombre pair : si à 0.5 près alors arrondi selon le bit de poids faible donc statistiquement 50% du temps au supérieur et 50% à l'inférieur
Le comportement recommandé est le dernier car statistiquement, les erreurs d'arrondis des .5 ne se cumulent pas mais s'annulent. En pratique, on obtient :
round(11.5) = 12
round(12.5) = 12
round(-11.5) = -12
round(-12.5) = -12
On comprend donc mieux le nom d'arrondi vers le nombre pair. Cet arrondi s'appelle aussi arrondi bancaire.
J'espère que vous avez appris quelque chose et qu'un bête arrondi n'a en fait rien de bête même si c'est utilisé quotidiennement à grande échelle.
Dans la même veine, vous pouvez découvrir en anglais les innombrables subtilités des nombres flottants.
Je laisse la main à quelqu'un d'autre dans la série "Cohérences" :)
# Merci
Posté par plr . Évalué à 3.
Merci pour ces curiosités.
En règle générale, je préfère les arrondis de Matlab; pour les impôts, je préfère Java.
D'ailleurs, complètement hs, sur ma taxe d'habitation, je n'ai pas réussi à trouver la règle des arrondis: en fonction des colonnes, les règles me semblaient différer, soit les calculs utilisaient les arrondis de certains résultats intermédiaires, soit les valeurs sans arrondis. Je n'ai pas creusé plus.
Le sujet des flottants/float est un sujet assez récurrent dans les forums en fonction des langages et librairies.
[^] # Re: Merci
Posté par Dring . Évalué à 3.
Pour tout ce qui est impôt, la loi privilégie toujours le contribuable. Si ça peut t'aider dans ta compréhension du bouzin…
[^] # Re: Merci
Posté par Marotte ⛧ . Évalué à 4.
Si je comprends correctement la notion d’« arrondi bancaire » c’est justement la méthode qui permet de ne privilégier ni le trésor ni le contribuable… (ni la banque ni le client, etc…)
[^] # Re: Merci
Posté par LupusMic (site web personnel, Mastodon) . Évalué à 3.
Pour tout ce qui est calcul monétaire, l'usage des nombres flottants devrait être illégal. Seul l'emploi d'une bibliothèque éprouvée pour les calculs monétaires devrait être considéré. J'ai travaillé sur quelques IS où PHP était utilisé, et les développeurs m'ayant précédé avaient opté pour des flottants, quand il s'agissait du prix des prestations… Évidement, au final, cela se traduisait par une comptabilité incohérente et des fausses factures, des faux bilans, etc. Finalement, l'usage des fonctions bc_* s'est généralisé pour travailler sur les nombres décimaux, alors que malheureusement, le web bouge vers le JS, qui est encore pire en matière de gestion de l'approximation de la représentation des nombres décimaux en nombres flottants, misère !
# Python(s)
Posté par gaaaaaAab . Évalué à 10.
En passant, Python2 renvoie -1, mais Python3 renvoie 0
[^] # Re: Python(s)
Posté par goabbear . Évalué à 3. Dernière modification le 30 novembre 2016 à 09:50.
oO
# -0
Posté par Liorel . Évalué à 4.
En pratique, la différence entre 0 et -0 est faible. Elle n'a d'importance que quand 0 se retrouve au dénominateur, ce qui ne devrait de toute façon pas arriver.
Un exemple en R :
Ça, ce sont les sources. Le mouton que tu veux est dedans.
[^] # Re: -0
Posté par gipoisson . Évalué à 1.
Quelques subtilités des
numeric
en R, type qui englobe lesinteger
s et lesdouble
s :[^] # Re: -0
Posté par Perthmâd (site web personnel) . Évalué à 6.
Je me souviens cependant d'un exposé d'un chercheur bossant sur la preuve de programmes flottants qui nous avait expliqué qu'un avion de chasse avait failli partir dans le décor à cause de cette différence…
# Haute précision
Posté par gipoisson . Évalué à 1.
Quid de bibliothèques de haute précision ? Par exemple, GNU MPFR implémente les cinq modes d'arrondis d'IEEE754-2008.
Disclaimer: n'ayant pas de grande aisance en C, je me fie au compilateur pour m'indiquer les éventuelles bourdes de ce que j'aurais commises.
# Java c'est plus fort que toi
Posté par Dring . Évalué à 5.
A noter que la classe BigDecimal de Java supporte tous les types d'arrondis possibles, y compris le Round Half Uneven que je n'ai pas vu cité dans les commentaires.
Il y a une page Wikipédia dédiée au sujet pour ceux que ça passionne : https://en.m.wikipedia.org/wiki/Rounding.
# Oui mais...
Posté par harlock974 . Évalué à 1.
… n'y a t-il pas un arrondi "légal" (celui qu'on apprend à l'école) ?
De mémoire 0.5 → 1 et -0.5 → -1
(j'ai un léger doute sur le dernier, 0 ou -1 ?)
[^] # Re: Oui mais...
Posté par Anthony Jaguenaud . Évalué à 2.
De mémoire en math la fonction
int
est définie et prend le nombre entier inférieur… donc -1,5 --> -2, pour l’arrondi, je ne sais pas s’il y a une définition mathématique.[^] # Re: Oui mais...
Posté par lasher . Évalué à 1.
Les langages de type C/C++/Java (implicitement, Scala/Clojure aussi du coup) utilisent l'arrondi mathématique classique. Par exemple:
… imprimera
round(0.5) = 1 (1.0)
.En Scala:
… imprimera
res0: Long = 1
dans l'interpréteur.[^] # Re: Oui mais...
Posté par 태 (site web personnel) . Évalué à 4.
Ce n'est pas un arrondi "légal" mais un arrondi "logique" au plus près pour les décimaux (https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero). L'idée est que si le premier chiffre après la troncature dans un nombre décimal est 5, les éventuels chiffres suivants ne peuvent que le faire s'éloigner de 0 donc 0.5 → 1 et -0.5 → -1.
Mais c'est logique pour les nombres décimaux, pas pour les flottants, doubles et tout ça.
[^] # Re: Oui mais...
Posté par Romuald Delavergne . Évalué à 1.
D'après mes cours de physique, c'est l'arrondi utilisé pour obtenir le nombre de chiffres significatifs.
# Virgule flottante
Posté par barmic . Évalué à 7.
Personnellement je considère les nombres à virgule flottante comme les dates : dès qu'il y en a un dans un programme, il y a (au moins) un bug :)
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Virgule flottante
Posté par lasher . Évalué à 4.
Y'a un gang de physiciens et mathématiciens appliqués qui viennent de sentir quelqu'un marcher sur leur tombe. Je leur file ton adresse ? :-)
# Comment arrondir une date ?
Posté par Victor STINNER (site web personnel) . Évalué à 2.
Je me suis frotté aux erreurs d'arrondi en concevant une API C pour manipuler des dates : https://haypo.github.io/pytime.html
J'en garde un drôle de souvenir. Avec le langage C, l'arrondit est implicite et les erreurs faciles à commettre.
L'arrondit Python de la fonction round() est l'arrondit par défaut du très sérieux standard IEEE 754 : https://en.wikipedia.org/wiki/Rounding#Round_half_to_even
Cet arrondit est celui qui produit le moins d'erreur d'un point de vue statistique :
"This method treats positive and negative values symmetrically, and is therefore free of sign bias. More importantly, for reasonable distributions of y values, the average value of the rounded numbers is the same as that of the original numbers."
# Paramètre
Posté par cluxter . Évalué à 2.
Personne n'a eu l'idée d'introduire un paramètre obligatoire dans ces fonctions d'arrondi pour dire quel type d'arrondi on souhaite avoir..?
# En Ada :)
Posté par Blackknight (site web personnel, Mastodon) . Évalué à 2.
Vous auriez été déçu si j'avais réagi pour promouvoir ce langage :)
En Ada, il y a 3 attributs pour faire ça :
- S'Rounding qui renvoie l'entier le plus loin de zéro
- S'Unbiased_Rounding qui ramène au plus proche entier pair
- S'Machine_Rounding dont la norme précise que le retour est spécifique à la machine cible
Merci pour ce journal rafraichissant en tout cas
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.