Floating point 正确四舍五入双精度除法

Floating point 正确四舍五入双精度除法,floating-point,ieee-754,numerical-analysis,numerical-computing,Floating Point,Ieee 754,Numerical Analysis,Numerical Computing,我正在使用以下算法进行双精度除法,并试图在浮点的软件仿真中使其正确舍入。 设a为被除数,b为除数 所有操作均在Q2.62中执行 倒数的初始近似为 b/2是b的有效位,加上隐式位,并右移一位。对于以下内容,当写入a或b时,它意味着a或b的有效位加上其隐式位 近似值为0x17504f33f9de6(0x5D413CCCFE779800,在Q2.62中) 之后,使用牛顿-拉斐逊迭代近似倒数: 对于倒数r,有6次这样的迭代。商q的计算方法是将r乘以a的(有效位) 商的额外调整步骤: 最后四舍五入为:

我正在使用以下算法进行双精度除法,并试图在浮点的软件仿真中使其正确舍入。 设a为被除数,b为除数

所有操作均在Q2.62中执行

倒数的初始近似为

b/2是b的有效位,加上隐式位,并右移一位。对于以下内容,当写入a或b时,它意味着a或b的有效位加上其隐式位

近似值为
0x17504f33f9de6
0x5D413CCCFE779800
,在Q2.62中)

之后,使用牛顿-拉斐逊迭代近似倒数:

对于倒数r,有6次这样的迭代。商q的计算方法是将r乘以a的(有效位)

商的额外调整步骤:

最后四舍五入为:

if a <= (a - q * b/2):
      result = final_biased_exponent | q
else
      result = final_biased_exponent | adjusted_q

如果a为了检查舍入问题(仅在舍入到最近或偶数模式下),我从头开始构建了IEEE-754
binary32
分区的仿真代码,以便于说明。一旦开始工作,我机械地将代码转换为IEEE-754
binary64
division的仿真代码。ISO-C99代码,包括我的测试框架,如下所示。该方法与asker算法略有不同,因为它在Q1.63算法中执行中间计算以获得最大精度,并使用8位或16位条目表作为倒数的起始近似值

舍入步骤基本上是从被除数中减去原始商和除数的乘积,形成余数
rem\u raw
。它还形成了剩余的
rem_inc
,这将由商增加1 ulp产生。通过构造,我们知道原始商足够精确,无论是它还是它的增量值都是正确的四舍五入结果。余数可以是正数、负数或混合负数/正数。数量级较小的余数对应于正确舍入的商

取整法线和次法线(后者固有的非规范化步骤除外)之间存在的唯一区别是,正常结果不会出现平局情况,而次法线结果可能会出现平局情况。比如说,

MilošD.Ercegovac和Tomás Lang,“数字算术”,摩根·考夫曼,2004年,p。452

在定点运算中,原始商和除数的乘积是双倍长度的乘积。为了精确计算余数而不丢失任何位,我们因此动态地更改定点表示以提供额外的分数位。为此,被除数被左移适当的位数。但是,因为我们从算法的构造中知道,初始商非常接近真实结果,所以我们知道,在从被除数进行减法的过程中,所有高阶位都将被抵消。所以我们只需要计算并减去低阶乘积位就可以计算出两个余数

因为[1,2]中的两个值的除法会得到(0.5,2)中的商,所以商的计算可能需要一个标准化步骤才能回到区间[1,2),并伴随指数校正。我们在排列减法的股息和商与除数的乘积时需要考虑这一点,请参见下面代码中的
normalization\u shift

由于下面的代码是探索性的,所以在编写时没有考虑到极端优化。可以进行各种调整,也可以用特定于平台的内部函数或内联汇编替换可移植代码。同样,下面的基本测试框架可以通过合并各种技术来生成难以理解的代码来加强-文献中的圆形案例。例如,我在过去使用了以下论文附带的除法测试向量:

Brigitte Verdonk,Annie Cuyt和Dennis Verschaeren.“用于测试浮点算术I的精度和范围独立工具:基本运算、平方根和余数”,《数学软件ACM交易》,第27卷,第1期,2001年3月,第92-118页

我的测试框架中基于模式的测试向量受以下出版物的推动:

N.L.Schryer,“计算机浮点单元的测试”,《计算机科学技术报告第89号》,美国电话电报公司贝尔实验室,新泽西州默里山(1981年)

#包括
#包括
#包括
#包括
#包括
#定义TEST\u FP32\u DIV(0)/*0:binary64除法;1:binary32除法*/
#定义纯随机(1)
#基于模式定义(2)
#定义测试模式(基于模式)
#定义ITO_TAKAGI_YAJIMA(1)/*更精确的往复起始近似*/
uint32\u t浮动\u作为uint32(浮动a)
{
uint32_t r;
memcpy(r&a、sizeof r);
返回r;
}
浮动uint32作为浮动(uint32 t a)
{
浮子r;
memcpy(r&a、sizeof r);
返回r;
}
uint32\u t umul32hi(uint32\u t a,uint32\u t b)
{
返回(uint32_t)((uint64_t)a*b)>>32;
}
int clz32(uint32_t a)
{
uint32_t r=32;
如果(a>=0x00010000){a>=16;r-=16;}
如果(a>=0x00000100){a>=8;r-=8;}
如果(a>=0x00000010){a>=4;r-=4;}
如果(a>=0x00000004){a>=2;r-=2;}
r-=a-(a&(a>>1));
返回r;
}
#如果伊藤高木野岛
/*伊藤正之,高木直文,Yajima Shuzo,“有效初始近似
通过与操作数的乘法进行乘法除法和平方根运算
修改“《IEEE计算机交易》,第46卷,第4期,1997年4月,
第495-498页。
*/
#定义日志2_选项卡_条目(6)
#定义制表符条目(1个FP32字节;
expo_y=(y&FP32_expo_MASK)>>FP32_MANT_位;
符号r=(x^y)和FP32符号掩码;
abs\ux=x&~FP32\u符号\u掩码;
abs\u y=y&~FP32\u符号\u掩码;
x_是_零=(abs_x==0);
你是零