Floating point 是";银行家';s四舍五入“;真的更稳定吗?
我所说的银行家四舍五入是指Floating point 是";银行家';s四舍五入“;真的更稳定吗?,floating-point,language-agnostic,rounding,floating-accuracy,Floating Point,Language Agnostic,Rounding,Floating Accuracy,我所说的银行家四舍五入是指 “四舍五入,五舍五入” 作为: 四舍五入到最接近的值;如果数字中途下降,则使用偶数(零)最低有效位四舍五入到最接近的值。这是二进制浮点的默认值,也是十进制的推荐默认值 据说这种方法比其他方法更可取 “四舍五入到最近,距离为零” 它“将四舍五入数字相加时的预期误差降至最低”。显然,这是“在最合理的分布上,它不像舍入半离零法那样受到负或正偏差的影响” 我不明白为什么会这样。直观地说,如果将0.0四舍五入为零,0.5“应该”四舍五入为零(如方法2所示)。这样,等量的数字将向
0.0
四舍五入为零,0.5
“应该”四舍五入为零(如方法2所示)。这样,等量的数字将向零和远离零取整。简单地说,如果浮点数用一个十进制数字表示,那么在十个数字中,0.0
,…,0.9
五个将向下舍入,五个将使用方法2向上舍入。类似地,对于1.0
,…,1.9
等
当然,浮点数是用二进制尾数表示的,但我认为上面的推理仍然适用。请注意,对于IEEE 754双精度,整数和整数加一半都可以精确地表示为绝对值,大约为2^52
,因此这些精确值实际上在实践中会出现
那么方法1如何更好呢?
对它确实在数值上更稳定
对于您正在查看的案例,数字[0.0,0.1,…,0.9]
,请注意,在舍入到“远离”的关系下,这些数字中只有四个向下舍入(0.1
到0.4
),五个向上舍入,一个(0.0
)通过舍入操作保持不变,当然,对于1.0
到1.9
,2.0
到2.9
,这种模式会重复。因此,平均而言,从零开始舍入的值比从零开始舍入的值多。但在与平的圆形关系下,我们会得到:
- 在
[0.0,0.9]
- 在
[1.0,1.9]
round
函数中的差异而带来的困难,我们给出了两个Python版本不可知的舍入函数:
def圆形到偶数(x):
"""
将浮点x四舍五入到最接近的整数,四舍五入到偶数。
"""
如果x<0:
返回-圆形到偶数(-x)#使用对称
内部零件,分形零件=divmod(x,1)
返回整数(整数部分)+(
压裂部分>0.5
或(分形部分==0.5和整数部分%2.0==1.0))
def圆形接头远离零点(x):
"""
将浮点x四舍五入到最接近的整数,将关系从零四舍五入。
"""
如果x<0:
返回-圆_ties _远离_zero(-x)#使用对称
内部零件,分形零件=divmod(x,1)
返回整数(整数部分)+(分数部分>=0.5)
现在,我们来看一下将这两个函数应用于范围[50.01000.0]
中小数点后的一位数字时引入的平均误差:
>>测试值=[n/10.0表示范围内的n(5001001)]
>>>错误\u偶数=[四舍五入\u到\u偶数(值)-测试值中的值对应值]
>>>errors_away=[取整_ties_away_from_zero(value)-测试值中值的值]
我们使用最近添加的统计
标准库模块来计算这些误差的平均值和标准偏差:
导入统计信息
>>>statistics.mean(错误为偶数),statistics.stdev(错误为偶数)
(0.0, 0.2915475947422656)
>>>statistics.mean(错误),statistics.stdev(错误)
(0.0499001996007984, 0.28723681870533313)
这里的关键点是错误\u甚至的平均值为零:平均误差为零。但是errors\u away
具有正平均值:平均误差偏离零
一个更现实的例子
这是一个半现实的例子,演示了在数值算法中圆结偏离零的偏差。我们要用这个算法计算一系列浮点数的和。该算法将要计算的和分成两个大致相等的部分,递归地对这两部分求和,然后将结果相加。它比简单的求和要精确得多,但通常不如更复杂的算法那样精确。这是NumPy的sum
函数使用的算法。下面是一个简单的Python实现
导入操作符
def pairwise_sum(xs,i,j,add=operator.add):
"""
返回浮点的总和xs[i:j](从0.0
到0.9
的十个数字中有0个,四个向下舍入,五个向上舍入,一个保持不变。@MarkDickinson啊,这是有道理的。除去整数,我想我看到了银行家的舍入是如何减少偏差的。这是一个很好的例子:从1.0
开始。添加epsilon/2
,subtractepsilon/2
,重复。从数学上讲,无论你重复多少次,结果都应该是1.0
。在向上取整的过程中,你会慢慢爬向2.0
@MarkDickinson。你能把你的评论转化为答案吗?我认为它很好地澄清了这个问题。我会努力找到时间。事实上,我很乐意看到这里的一位专家给出了一个经过适当研究的答案:我从理论上知道,有一些真正的算法会受到“漂移”的影响