c-浮点平方根倒数法校正舍入



我已经使用Newton-Raphson方法(在汇编中)实现了一个32位IEEE-754浮点平方根,该方法基于平方根的倒数。我使用的是四舍五入法。我的平方根方法只接受归一化值和零,但不接受非归一化值或特殊值(NaN、Inf等)

我想知道如何实现正确的舍入(使用类似汇编的指令),以便我的结果对所有输入都是正确的(符合IEEE-754)?基本上,我知道如何测试我的结果是否正确,但我想调整下面的算法,以便获得正确的四舍五入结果。我应该向算法中添加哪些指令?

请参阅:确定浮点平方根获取更多信息

谢谢!

只有大约20亿个float符合您的描述。全部尝试,与C库中的sqrtf进行比较,并检查所有差异。如果您担心的话,可以使用C库中的sqrtsqrtl来获得更高精度的平方根。然而,sqrtsqrtfsqrtl被典型的C库正确地四舍五入,因此应该进行直接比较。

为什么不把结果平方,如果它不等于输入,加或减(取决于差的符号)一个最低有效位,平方,然后检查是否会得到更好的结果?

这里更好可能意味着绝对差异更小。唯一可能变得棘手的情况是用尾数"打"√2,但这可以一劳永逸地检查。

编辑

我意识到以上的答案是不够的。简单地在32位FP中求平方并与输入进行比较并不能提供足够的信息。假设y=your_sqrt(x)。将y2与x进行比较,发现y2>x、 从y中减去1 LSB得到z(在你的评论中是y1),然后将z2与x进行比较,发现不仅z2<x、 但是,在可用的位中,y2-x==x-z2-如何在y和z之间选择?你应该使用所有的比特(我想这就是你想要的),或者至少使用更多的比特(这也是njuffa的建议)。

从你的评论中,我怀疑你使用的是严格的32位硬件,但让我假设你有一个32位乘32位的整数乘法,64位的结果可用(如果没有,它可以构造)。如果你把y的尾数的23位作为一个整数,在前面放一个1,然后将其自身相乘,你就得到了一个数字,除了可能额外偏移1之外,你可以直接与x的尾数进行比较,方法相同。这样,您就有了所有48位可用于比较,并且可以在没有任何近似的情况下决定是否是abs(y2-x)≷abs(z2-x)。

如果你不确定离最终结果在一个LSB以内(但你确定不会远得多),你应该重复上面的步骤,直到y2-x改变符号或达到0。不过,要注意边缘情况,这基本上应该是指数调整的情况,因为尾数是2的幂。

记住,正浮点数可以正确地作为整数进行比较,这也很有帮助,至少在1.0F为0x3f800000的机器上是这样。

最新更新