Algorithm 哪个浮点比较更准确,为什么?
我正在试验牛顿法计算平方根的不同实现。一个重要的决定是何时终止算法 显然,使用Algorithm 哪个浮点比较更准确,为什么?,algorithm,floating-point,numerical-analysis,Algorithm,Floating Point,Numerical Analysis,我正在试验牛顿法计算平方根的不同实现。一个重要的决定是何时终止算法 显然,使用y*y和x之间的绝对差是不行的,其中y是x平方根的当前估计值,因为对于x的大值,可能无法以足够的精度表示其平方根 所以我应该使用相对标准。天真的我会用这样的东西: static int sqrt_good_enough(float x, float y) { return fabsf(y*y - x) / x < EPS; } static int sqrt足够好(float x,float y){ 返回f
y*y
和x
之间的绝对差是不行的,其中y
是x
平方根的当前估计值,因为对于x
的大值,可能无法以足够的精度表示其平方根
所以我应该使用相对标准。天真的我会用这样的东西:
static int sqrt_good_enough(float x, float y) {
return fabsf(y*y - x) / x < EPS;
}
static int sqrt足够好(float x,float y){
返回fabsf(y*y-x)/x
这似乎效果很好。但最近我开始阅读Kernighan和Plauger的《编程风格的要素》,他们在第1章中为相同的算法提供了一个Fortran程序,其终止标准(翻译为C)为:
static int sqrt_good_enough(float x, float y) {
return fabsf(x/y - y) < EPS * y;
}
static int sqrt足够好(float x,float y){
返回fabsf(x/y-y)
两者在数学上是等价的,但是有没有理由选择一种形式而不是另一种形式呢?它们仍然是不等价的;底部的一个在数学上等价于fabsf(y*y-x)/(y*y)
y*y
溢出(可能是因为x
是FLT\u MAX
并且y
被不幸选择),那么终止可能永远不会发生。下面的交互使用double
>>> import math
>>> x = (2.0 - 2.0 ** -52) * 2.0 ** 1023
>>> y = x / math.sqrt(x)
>>> y * y - x
inf
>>> y == 0.5 * (y + x / y)
True
编辑:正如一条评论(现已删除)所指出的,在迭代和终止测试之间共享操作也很好
EDIT2:两者都可能存在低于正常值的
x
问题。规范化x
以避免两个极端的复杂性。这两个在数学上实际上并不完全相等,除非您为第一个极端编写fabsf(y*y-x)/(y*y)x = 6.800000000000002
yprev = 0
y = 2
while abs(y*y - x) > eps*abs(y*y)
yprev = y;
y = 0.5*(y + x/y);
end
C/C++版本也有同样的问题。对于一个以计算机上的数值计算为目标的beta StackExchange社区来说,这是一个很好的问题。溢出问题是我从未想到过的一个极好的问题。顺便说一下,注释(编辑1)现在移动到我的答案。