是的,interpol_80() 是安全的,我们来演示一下。
问题指出输入是 64 位浮点数
rnd64(ui) = ui
结果就是(假设 * 和 + 是数学运算)
r = u2*(1-u1)+(u1*u3)
四舍五入到 64 位浮点数的最佳返回值是
r64 = rnd64(r)
因为我们有这些属性
u2 <= r <= u3
保证
rnd64(u2) <= rnd64(r) <= rnd64(u3)
u2 <= r64 <= u3
转换为 80 位的 u1,u2,u3 也是准确的。
rnd80(ui)=ui
现在,让我们假设0 <= u2 <= u3
,然后执行不精确的浮点运算会导致最多 4 个舍入错误:
rf = rnd(rnd(u2*rnd(1-u1)) + rnd(u1*u3))
假设四舍五入到最接近的偶数,这将最多与精确值相差 2 ULP。如果使用 64 位浮点数或 80 位浮点数进行舍入:
r - 2 ulp64(r) <= rf64 <= r + 2 ulp64(r)
r - 2 ulp80(r) <= rf80 <= r + 2 ulp80(r)
rf64
可以关闭 2 ulp 所以 interpol-64() 是不安全的,但是呢rnd64( rf80 )
?
我们可以这样说:
rnd64(r - 2 ulp80(r)) <= rnd64(rf80) <= rnd64(r + 2 ulp80(r))
既然0 <= u2 <= u3
,那么
ulp80(u2) <= ulp80(r) <= ulp80(r3)
rnd64(u2 - 2 ulp80(u2)) <= rnd64(r - 2 ulp80(r)) <= rnd64(rf80)
rnd64(u3 + 2 ulp80(u3)) >= rnd64(r + 2 ulp80(r)) >= rnd64(rf80)
幸运的是,就像(u2-ulp64(u2)/2 , u2+ulp64(u2)/2)
我们得到的范围内的每个数字一样
rnd64(u2 - 2 ulp80(u2)) = u2
rnd64(u3 + 2 ulp80(u3)) = u3
自从ulp80(x)=ulp62(x)/2^(64-53)
我们由此得到证明
u2 <= rnd64(rf80) <= u3
对于 u2 <= u3 <= 0,我们可以轻松地应用相同的证明。
最后要研究的情况是 u2 <= 0 <= u3。如果我们减去 2 个大值,那么结果可以达到 ulp(big)/2 off 而不是 ulp(big-big)/2...
因此我们所做的这个断言不再成立:
r - 2 ulp64(r) <= rf64 <= r + 2 ulp64(r)
幸运的是,u2 <= u2*(1-u1) <= 0 <= u1*u3 <= u3
这是在四舍五入后保留的
u2 <= rnd(u2*rnd(1-u1)) <= 0 <= rnd(u1*u3) <= u3
因此,由于添加量的符号相反:
u2 <= rnd(u2*rnd(1-u1)) + rnd(u1*u3) <= u3
四舍五入后也是如此,所以我们可以再次保证
u2 <= rnd64( rf80 ) <= u3
量子点
为了完整起见,我们应该关注非正规输入(逐渐下溢),但我希望你不会对压力测试那么恶毒。我不会演示这些会发生什么...
编辑:
这是一个后续,因为以下断言有点近似,并且在 0 <= u2 <= u3 时生成了一些注释
r - 2 ulp80(r) <= rf80 <= r + 2 ulp80(r)
我们可以写出以下不等式:
rnd(1-u1) <= 1
rnd(1-u1) <= 1-u1+ulp(1)/4
u2*rnd(1-u1) <= u2 <= r
u2*rnd(1-u1) <= u2*(1-u1)+u2*ulp(1)/4
u2*ulp(1) < 2*ulp(u2) <= 2*ulp(r)
u2*rnd(1-u1) < u2*(1-u1)+ulp(r)/2
对于下一次舍入操作,我们使用
ulp(u2*rnd(1-u1)) <= ulp(r)
rnd(u2*rnd(1-u1)) < u2*(1-u1)+ulp(r)/2 + ulp(u2*rnd(1-u1))/2
rnd(u2*rnd(1-u1)) < u2*(1-u1)+ulp(r)/2 + ulp(r)/2
rnd(u2*rnd(1-u1)) < u2*(1-u1)+ulp(r)
对于总和的第二部分,我们有:
u1*u3 <= r
rnd(u1*u3) <= u1*u3 + ulp(u1*u3)/2
rnd(u1*u3) <= u1*u3 + ulp(r)/2
rnd(u2*rnd(1-u1))+rnd(u1*u3) < u2*(1-u1)+u1*u3 + 3*ulp(r)/2
rnd(rnd(u2*rnd(1-u1))+rnd(u1*u3)) < r + 3*ulp(r)/2 + ulp(r+3*ulp(r)/2)/2
ulp(r+3*ulp(r)/2) <= 2*ulp(r)
rnd(rnd(u2*rnd(1-u1))+rnd(u1*u3)) < r + 5*ulp(r)/2
我没有证明最初的说法,但不是那么远......