确定浮点平方根
如何确定浮点数的平方根?牛顿-拉夫森法是个好方法吗?我也没有硬件平方根。我也没有硬件除法(但是我已经实现了浮点除法)。
如果可能的话,我宁愿尽量减少分割的数量,因为它们是如此昂贵。
另外,减少迭代总数的初始猜测应该是什么?
非常感谢!
回答:
当您使用Newton-Raphson计算平方根时,您实际上想使用迭代来找到倒数平方根(此后,您可以简单地乘以输入值(并舍入四舍五入)以产生平方根)。
更准确地说:我们使用函数f(x) = x^-2 - n
。显然,如果f(x) = 0
,则x = 1/sqrt(n)
。这引起了牛顿迭代:
x_(i+1) = x_i - f(x_i)/f'(x_i) = x_i - (x_i^-2 - n)/(-2x_i^-3)
= x_i + (x_i - nx_i^3)/2
= x_i*(3/2 - 1/2 nx_i^2)
注意(与平方根的迭代不同),平方根的倒数不涉及除法运算,因此通常效率更高。
我在关于鸿沟的问题中提到,您应该查看现有的软浮动库,而不是重新发明轮子。该建议也适用于此。此功能已在现有的软浮点库中实现。
编辑:提问似乎依然混淆,让我们工作的例子:sqrt(612)
。 612
是1.1953125 x 2^9
(或b1.0011001 x
2^9,如果您更喜欢二进制)。拉出指数(9)的偶数部分,将输入写为f * 2^(2m)
,其中m
是整数,f
并且在[1,4)范围内。然后我们将有:
sqrt(n) = sqrt(f * 2^2m) = sqrt(f)*2^m
将这个减少应用于我们的例子给出f = 1.1953125 * 2 = 2.390625
(b10.011001
)和m = 4
。现在进行牛顿-
拉普森迭代x =
1/sqrt(f),使用0.5的初始猜测值进行查找(正如我在评论中指出的那样,该猜测值收敛于所有f
,但是使用线性近似作为初始猜测值可以做得更好):
x_0 = 0.5x_1 = x_0*(3/2 - 1/2 * 2.390625 * x_0^2)
= 0.6005859...
x_2 = x_1*(3/2 - 1/2 * 2.390625 * x_1^2)
= 0.6419342...
x_3 = 0.6467077...
x_4 = 0.6467616...
因此,即使有了(相对较差的)初始猜测,我们也可以快速收敛到的真实值1/sqrt(f) = 0.6467616600226026
。
现在我们简单地组装最终结果:
sqrt(f) = x_n * f = 1.5461646...sqrt(n) = sqrt(f) * 2^m = 24.738633...
并检查:sqrt(612)= 24.738633 …
显然,如果要正确舍入,则需要仔细分析以确保在计算的每个阶段都具有足够的精度。这需要仔细的簿记,但这不是火箭科学。您只需保持谨慎的错误界限,并通过算法传播它们。
如果要纠正舍入而不显式检查残差,则需要将sqrt(f)计算为2p +
2位的精度(其中p是源和目标类型的精度)。但是,您也可以采用将sqrt(f)计算为p位多一点的策略,对该值取平方,并在必要时将尾随位调整一位(这通常更便宜)。
sqrt很不错,因为它是一元函数,这使得在商品硬件上对单精度进行详尽的测试成为可能。
您可以sqrtf
在opensource.apple.com上找到OS
X软浮点函数,该函数使用上述算法(我写了它,发生了)。它是根据APSL许可的,可能适合或不适合您的需求。
以上是 确定浮点平方根 的全部内容, 来源链接: utcz.com/qa/400358.html