2017-06-19 113 views
4

对于IEEE-754算术,在倒数的最后一位准确度中是否有0或1个单位的保证?那么,对于互惠的倒数是否有保证的误差?浮点相互总是往返吗?

+0

这个问题是隐隐恒定的倒数,然后取整到单精度,也由马克回答了有关实施单精度乘法的问题由双精度乘法:https://开头计算器.com/questions/19589973 /实现单精度分割为双精度乘法 –

回答

9

[下面一切假定固定的IEEE 754的二进制格式,以某种形式的舍入到最近的作为舍入模式。]

由于倒数(计算为1/x)是一种基本的算术运算,1是完全可表示,并且算术运算保证按标准正确舍入,倒数结果保证在真值的最后位置处于0.5单位内。 (这适用于在标准中规定的基本的算术运算的任何。)

x不保证等于x,在一般的倒数的倒数。一个简单的例子与IEEE 754 binary64格式:避免

>>> x = 1.8 
>>> 1.0/(1.0/x) 
1.7999999999999998 
>>> x == 1.0/(1.0/x) 
False 

然而,假定溢和下溢,并且x是有限的,非零值,和精确表示,下面的结果都为真:

  1. 1.0/(1.0/x)的值与x的差异不会超过1个单位。

  2. 如果x尾数(归一化至处在范围[1.0, 2.0)照例)比sqrt(2)小,则倒数确实往返:1.0/(1.0/x) == x

证明素描:不失一般性,我们可以假设x为正,并且通过两个功率尺度x,使其处于范围[1.0, 2.0)。上述结果在x是2的精确幂的情况下显然是正确的,所以我们假设它不是(这将在下面的第二步中有用)。以下证明是针对IEEE 754二进制64格式的特定精度给出的,但它直接适用于任何IEEE 754二进制格式。

真正值倒数的舍入之前,写1/x,让y是(独一无二的,因为它原来)最接近的可表示binary64浮到1/x。然后:

  • 因为y是最接近浮子1/x,都y1/x都在binade [0.5, 1.0],其中连续彩车之间的间距正好是2^-53,我们有|y - 1/x| <= 2^-54。事实上,我们可以做得更好一些:

  • 我们实际上有一个严格的不平等以上:|y - 1/x| < 2^-54。如果|y - 1/x|刚好等于2^-54,那么1/x将精确地表示为任意精度二进制浮点数(因为y2^-54都是)。但唯一的二进制浮点数x其中1/x可以精确地表示一个精度是2的幂,我们已经排除了这种情况。

  • 如果x < sqrt(2)然后1/x > x/2,因此(四舍五入既最接近的可表示浮动),我们有y >= x/2,所以x/y <= 2

  • 现在x - 1/y = (y - 1/x) x/y,并从|y - 1/x|x/y边界(仍假设x < sqrt(2))我们得到|x - 1/y| < 2^-53。因此,x1/y,1/y轮到x最接近的浮点数,并且往返成功。这完成了第2部分的证明。

  • 在一般情况下,我们有x/y < 4,所以|x - 1/y| < 2^-52。这使得1/y至多1 ULP从x远,完成的部分证明1.

这里的sqrt(2)门槛的演示:使用Python,我们就范围[1.0, 2.0)百万随机花车,并确定那些不能通过互惠的。所有小于sqrt(2)的样本均通过往返。

>>> import random 
>>> samples = [random.uniform(1.0, 2.0) for _ in range(10**6)] 
>>> bad = [x for x in samples if 1.0/(1.0/x) != x] 
>>> len(bad) 
171279 
>>> min(bad) 
1.4150519879892107 
>>> import math 
>>> math.sqrt(2) 
1.4142135623730951 

而一个示范的最大误差不超过1 ULP,一般来说(对于binary64格式,在binade [1.0,2.0),在最后一个地方1个单元是2^-52) :

>>> samples = [random.uniform(1.0, 2.0) for _ in range(10**6)] 
>>> max(abs(x - 1.0/(1.0/x)) for x in samples) 
2.220446049250313e-16 
>>> 2**-52 
2.220446049250313e-16 

下面是与IEEE 754 binary64格式示出了如何避免下溢的限制是必要的一个例子:

>>> x = 1.3e308 
>>> x_roundtrip = 1.0/(1.0/x) 
>>> x.hex() 
'0x1.72409614c1e6ap+1023' 
>>> x_roundtrip.hex() 
'0x1.72409614c1e6cp+1023' 

这里x_roundtrip结果从与原来的b的不同之y两个单位,因为1/x小于最小的正常可表示的浮点数,因此与x的表示精度相同。最后说明:由于IEEE 754-2008也涵盖了十进制浮点类型,所以我应该提到,上述证明几乎是逐字进行到十进制的情况下,确定对于有效数小于sqrt(10)的浮点数,会发生往返,而对于一般的十进制浮点数(再次避免溢出和下溢),我们永远不会超过一个单位在最后的地方。然而,需要一些数论理论来证明关键不等式|x - 1/y| < 1/2 10^(1-p)始终是严格的:最终必须证明数量1 + 16 10^(2p-1)永远不是平方数(这是真的,但它可能超出了本网站的范围在这里包括证明)。

>>> from decimal import Decimal, getcontext 
>>> import random 
>>> getcontext().prec = 6 
>>> samples = [+Decimal(random.uniform(1.0, 10.0)) for _ in range(10**6)] 
>>> bad = [x for x in samples if 1/(1/x) != x] 
>>> min(bad) 
Decimal('3.16782') 
+1

嗯......我不得不查找“ambit”。 –