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

Spa*_*awk 11 math printf

我正在printf我的系统上测试两种不同的实现:printf (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
Run Code Online (Sandbox Code Playgroud)

在这里,两者显然都是半圆的。但是,当我测试四舍五入到第一个小数位时,事情变得混乱。也就是说,我正在测试 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
Run Code Online (Sandbox Code Playgroud)

两种实现的做法都不一样,而且我都看不到任何明确的模式。这两个printfs如何四舍五入到小数点后一位?

Mic*_*mer 19

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

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

  • 请注意,x.25 和 x.75(对于适当小的 x)确实具有精确的二进制表示形式,与其他表示不同。 (3认同)