Comment printf arrondit-il la moitié à la première décimale?


11

Je teste deux implémentations différentes de printfsur mon système printf (GNU coreutils) 8.26:, et la version fournie avec zsh 5.3.1. Je teste comment les demi-nombres sont arrondis, c'est-à-dire pour 1,5, 2,5, 3,5,… 9,5.

$ for i in {1..9}; do /usr/bin/printf '%.0f\n' "${i}.5"; done
2
2
4
4
6
6
8
8
10
$ for i in {1..9}; do printf '%.0f\n' "${i}.5"; done
2
2
4
4
6
6
8
8
10

Ici, les deux arrondissent clairement la moitié pour égaliser . Cependant, lorsque je teste l'arrondi à la première décimale, les choses deviennent confuses. Autrement dit, je teste 1.15, 1.25, 1.35,… 1.95.

$ for i in {1..9}; do /usr/bin/printf '%.1f\n' "1.${i}5"; done
1.1
1.2
1.4
1.5
1.5
1.6
1.8
1.9
2.0
$ for i in {1..9}; do printf '%.1f\n' "1.${i}5"; done
1.1
1.2
1.4
1.4
1.6
1.6
1.8
1.9
1.9

Les deux implémentations le font différemment, et je ne vois aucun modèle clair dans les deux. Comment ces deux printfmoitiés rondes s à la première décimale?

Réponses:


19

GNU printf utiliselong double alors que zsh utilise des doubles réguliers . Le comportement d'arrondi que vous voyez est dû au fait que (disons) 1,45 ne peut pas être représenté comme une somme de puissances de 2, c'est ainsi que fonctionne la représentation en virgule flottante IEEE 754 , et l'approximation la plus proche varie en fonction de la précision. C'est légèrement plus (avec 80 bits) ou moins (avec 64 bits), arrondissant ainsi vers le haut ou vers le bas comme vous le voyez.

Comme toujours, si vous vous souciez de la représentation et de l'arrondi précis au niveau humain, n'utilisez pas de virgule flottante.


1
Juste une note que x.25 et x.75 (pour un x convenablement petit) ont des représentations binaires exactes, contrairement aux autres.
Toby Speight
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.