半精确浮点对象中的Bug

我5月8日的帖子是关于“半精度”和“四分之一精度”的算术。我还为对象添加了代码fp16fp8克里夫的实验室.几天前,我从曼彻斯特大学的皮埃尔·布兰查德(Pierre Blanchard)和我的好朋友尼克·海厄姆(Nick Higham)那里听说,这些对象的构造器中有一个严重的bug。

内容

这个错误

格式e =每股收益(fp16 (1))
e = 9.765625000000000 e-04

的价值e

1/1024
ans = 9.765625000000000 e-04

这是半精度浮点数的相对精度,半精度浮点数在1和2之间的间隔。在二进制中,1之后的下一个数是

disp(二进制(1 + e))
0 01111 0000000001

2之前的最后一个数是

disp(二进制(双电子))
0 01111 1111111111

显示的三个字段是符号,1位,指数,5位,分数,10位。

到目前为止,一切顺利。当我试图转换任意数字时,就会出现错误双电子2half-precision。在这些极限之间没有更多的半精确数字了。区间下半部分的值应该舍入为双电子上半部分的值应该四舍五入为2.四舍五入的惯例是,双电子/ 2应改为2

但我没有注意如何舍入。我只是用了MATLAB函数,它不遵循round-to-even约定。更糟糕的是,我没有检查分数是否四舍五入到指数字段。我试着在一个声明中做所有的事情。

dbtypeoldfp1648:49
48 u = bitxor(uint16(round(1024*f)),…49 bitshift (uint16 (e + 15), 10));

之间的值双电子/ 22,圆(1024 * f)1024,它需要11位。的bitxor然后对指数字段进行重击。我不会在这里展示结果。如果您的机器上有May半精度对象,请尝试一下。

这不仅仅发生在稍微小于2的值上,它发生在接近任何2的幂上。

修复

我们需要一个合适的整数到最接近偶数的函数。

dbtypefp1631
31 rndevn = @(s) round(s-(rem(s,2)==0.5));

那就不要试图一次做完所有的事情。

dbtypefp1650:56
50% normal 51 t = uint16(rndevn(1024*f));52 if t==1024 53 t= uint16(0);e = e+1;55 end 56 u = bitxor(t, bitshift(uint16(e+15),10));

结果证明,非正态分布是可以的,就一次取而代之的是rndeven.分母的指数都是零,所以当分数蚕食时,就会得到正确的结果。

四分之一精度构造函数也需要类似的修复,fp8

克里夫的实验室

我正在更新密码MATLAB中央文件交换.只有@fp16 / fp16@fp8 fp8 /都受到影响。(给我几天时间来完成更新过程。)

谢谢

感谢皮埃尔和尼克。




发布与MATLAB®R2017a

|

评论

要留下评论,请点击在这里登录到您的MathWorks帐户或创建一个新帐户。