In che modo printf arrotonda a metà al primo decimale?


11

Sto testando due diverse implementazioni di printfsul mio sistema: printf (GNU coreutils) 8.26e la versione inclusa zsh 5.3.1. Sto testando come arrotondare la metà dei numeri, ovvero per 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

Qui, entrambi chiaramente arrotondano la metà a pari . Tuttavia, quando provo ad arrotondare al primo decimale, le cose diventano confuse. Cioè, sto testando per 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

Entrambe le implementazioni lo fanno diversamente, e non riesco a vedere alcun modello chiaro in entrambi. Come fanno queste due printfmetà arrotondate al primo decimale?

Risposte:


19

GNU printf usalong double mentre zsh usa doubles regolari . Il comportamento di arrotondamento che vedi è perché (diciamo) 1.45 non può essere rappresentato come una somma di potenze di 2, ovvero come funziona la rappresentazione in virgola mobile IEEE 754 e l'approssimazione più vicina varia in base alla precisione. È leggermente più (con 80 bit) o ​​meno (con 64 bit), arrotondando così su o giù come vedi.

Come sempre, se ti interessa la rappresentazione e l'arrotondamento accurati a livello umano, non usare il virgola mobile.


1
Solo una nota che x.25 e x.75 (per una x adeguatamente piccola) hanno rappresentazioni binarie esatte, a differenza delle altre.
Toby Speight,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.