作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
考虑形式为 0.xx5
的浮点数集合。之间0.0
和 1.0
:[0.005, 0.015, 0.025, 0.035, ..., 0.985, 0.995]
我可以在 Python 中轻松列出所有 100 个这样的数字:
>>> values = [n/1000 for n in range(5, 1000, 10)]
让我们看看前几个和最后几个值来检查我们没有犯任何错误:
>>> values[:8]
[0.005, 0.015, 0.025, 0.035, 0.045, 0.055, 0.065, 0.075]
>>> values[-8:]
[0.925, 0.935, 0.945, 0.955, 0.965, 0.975, 0.985, 0.995]
现在我想将这些数字中的每一个四舍五入到点后两位小数。一些数字将被四舍五入;有些会被四舍五入。我有兴趣准确计算有多少舍入。我也可以在 Python 中轻松计算:
>>> sum(round(value, 2) > value for value in values)
50
所以事实证明,这 100 个数字中正好有一半被四舍五入了。
round
函数使用舍入到偶数(又名银行家的舍入)作为其舍入模式,因此您希望这些值交替向上舍入和向下舍入。
0.125
、
0.375
、
0.625
和
0.875
),这些值不是精确的关系,而只是非常这些关系的良好二进制近似。毫不奇怪,对舍入结果的仔细检查表明这些值不会交替上下舍入。相反,每个值向上或向下舍入取决于二进制近似值发生在十进制值的哪一侧。所以没有先验的理由期望值的一半向上取整,一半取下。这让我们得到的结果正好是 50 有点令人惊讶。
>>> values = [n/10**7 for n in range(5, 10**7, 10)]
>>> sum(round(value, 6) > value for value in values)
500000
这里再次将明显的联系四舍五入到点后的小数点后 8 位:
>>> values = [n/10**9 for n in range(5, 10**9, 10)]
>>> sum(round(value, 8) > value for value in values)
50000000
所以问题是:为什么正好有一半的案例四舍五入?或者换句话说,为什么在这些小数关系的所有二进制近似值中,大于真实值的近似值数量与较小的近似值数量完全匹配? (可以很容易地证明,对于精确的情况,我们将有相同数量的向上舍入和向下舍入,因此我们可以忽略这些情况。)
round
函数将使用舍入到偶数舍入模式正确舍入操作。虽然语言本身不能保证这一切,但这种行为非常普遍,我们假设在这个问题中使用了这样一台典型的机器。 最佳答案
不是答案,只是想充实一下令人费解的地方。这当然不是“随机”,但请注意这还不够 ;-) 看看具体的两位数案例:
>>> from decimal import Decimal as D
>>> for i in range(5, 100, 10):
... print('%2d' % i, D(i / 100))
5 0.05000000000000000277555756156289135105907917022705078125
15 0.1499999999999999944488848768742172978818416595458984375
25 0.25
35 0.34999999999999997779553950749686919152736663818359375
45 0.450000000000000011102230246251565404236316680908203125
55 0.5500000000000000444089209850062616169452667236328125
65 0.65000000000000002220446049250313080847263336181640625
75 0.75
85 0.84999999999999997779553950749686919152736663818359375
95 0.9499999999999999555910790149937383830547332763671875
现在您可以配对
i/100
与
(100-i)/100
并且它们的数学总和正好是 1。所以这对,在上面,5 与 95,15 与 85,等等。 5 次向上舍入的确切机器值,而 95 次向下舍入的机器值,这是“预期的”:如果真和为 1,并且一个加数“向上舍入”,那么肯定另一个“向下舍入”。
10**3
做了,
10**7
, 和
10**9
,并且我也验证了指数 2、4、5、6、8、10 和 11 的精确平衡成立。
10**n
,如果我们乘以它的倒数呢?与上面的对比:
>>> for i in range(5, 100, 10):
... print('%2d' % i, D(i * (1 / 100)))
5 0.05000000000000000277555756156289135105907917022705078125
15 0.1499999999999999944488848768742172978818416595458984375
25 0.25
35 0.350000000000000033306690738754696212708950042724609375
45 0.450000000000000011102230246251565404236316680908203125
55 0.5500000000000000444089209850062616169452667236328125
65 0.65000000000000002220446049250313080847263336181640625
75 0.75
85 0.84999999999999997779553950749686919152736663818359375
95 0.95000000000000006661338147750939242541790008544921875
现在有 7 个(而不是 5 个)案例。
10**3
, 64 (而不是 50) 向上取整;为
10**4
, 828(而不是 500),用于
10**5
, 9763(而不是 5000);等等。因此,在计算中不超过一个舍入误差是非常重要的
i/10**n
.
关于python - 解释区间 [0, 1] 中明显联系的舍入方向上的惊人奇偶性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62721186/
我是一名优秀的程序员,十分优秀!