printf如何将一半舍入到小数点后第一位?


11

我正在系统上测试的两种不同实现printfprintf (GNU coreutils) 8.26和与捆绑在一起的版本zsh 5.3.1。我正在测试如何舍入一半的数字,即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

在这里,两者显然都舍入为一半。但是,当我测试四舍五入到小数点后第一位时,事情变得令人困惑。也就是说,我正在测试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

两种实现方式都不同,并且我都看不到任何清晰的模式。这两个printf半数如何舍入到小数点后第一位?

Answers:


19

GNU printf 使用long double zsh 使用常规doubles。您看到的舍入行为是因为(例如)1.45不能表示为2的幂的和,这就是IEEE 754浮点表示的工作方式,并且最接近的近似值根据精度而变化。它稍微多一点(80位)或更少(64位),因此如您所见向上或向下舍入。

与以往一样,如果您关心准确的人员级表示和舍入,请不要使用浮点数。


1
请注意,x.25和x.75(适用于较小的x)确实具有精确的二进制表示形式,与其他形式不同。
Toby Speight
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.