首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >浮点平方根算法

浮点平方根算法
EN

Stack Overflow用户
提问于 2013-07-02 01:36:56
回答 1查看 1.7K关注 0票数 1

我想知道谁可以为我提供一些浮点平方根算法的例子,可以利用硬件除法器。

额外的细节:我有一个正在开发的浮点单元,它有一个硬件浮点IEEE-754 32位乘法器,加法器和除法器。我已经使用牛顿-拉夫森方法实现了平方根,只使用了乘法和加法/减法,但现在我想比较一下,如果我有一个可用的硬件除法器,平方根的吞吐量。

1难以精确计算的特定输入是0x7F7FFFFF的平方根(3.4028234663852886E38)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-07-02 04:13:22

@tmyklebu提供的解决方案看起来肯定能满足您的需求。

代码语言:javascript
复制
r = input value
s(0) = initial estimate of sqrt(r).  Example: r with its exponent halved.
s(n) = sqrt(r)

S <- (s + r/s)/2

它具有二次收敛性,执行所需的除法。N=3或4应适用于32位浮点数。

编辑N=2表示32位浮点型,N=3(可能是4)表示双精度

编辑每个操作请求

代码语言:javascript
复制
// Initial estimate
static double S0(double R) {
  double OneOverRoot2 = 0.70710678118654752440084436210485;
  double Root2        = 1.4142135623730950488016887242097;
  int Expo;
  // Break R into mantissa and exponent parts.
  double Mantissa = frexp(R, &Expo);
  int j;
  printf("S0 %le %d %le\n", Mantissa, Expo, frexp(sqrt(R), &j));
  // If exponent is odd ...
  if (Expo & 1) {
    // Pretend the mantissa [0.5 ... 1.0) is multiplied by 2 as Expo is odd, 
    //   so it now has the value [1.0 ... 2.0)
    // Estimate the sqrt(mantissa) as [1.0 ... sqrt(2))
    // IOW: linearly map (0.5 ... 1.0) to (1.0 ... sqrt(2))
    Mantissa = (Root2 - 1.0)/(1.0 - 0.5)*(Mantissa - 0.5) + 1.0;
  }
  else {
    // The mantissa is in range [0.5 ... 1.0)
    // Estimate the sqrt(mantissa) as [1/sqrt(2) ... 1.0)
    // IOW: linearly map (0.5 ... 1.0) to (1/sqrt(2) ... 1.0)
    Mantissa = (1.0 - OneOverRoot2)/(1.0 - 0.5)*(Mantissa - 0.5) + OneOverRoot2;
  }
  // Form initial estimate by using the above mantissa estimate and exponent/2
  return ldexp(Mantissa, Expo/2);
}

// S = (S + R/S)/2 method
double Sqrt(double R) {
  double S = S0(R);
  int i = 5;  // May be reduced to 3 or 4 for double and 2 for float
  do {
    printf("S  %u %le %le\n", 5-i, S, (S-sqrt(R))/sqrt(R));
    S = (S + R/S)/2;
  } while (--i);
  return S;
}

void STest(double x) {
  printf("T  %le %le %le\n", x, Sqrt(x), sqrt(x));
}

int main(void) {
  STest(612000000000.0);
  return 0;
}

对于double在3次迭代后收敛。

S0 5.566108e-01 40 7.460635e-01

S 0 7.762279e+05 -7.767318e-03

S 1 7.823281e+05 3.040175e-05

S 2 7.823043e+05 4.621193e-10

S3 7.823043e+05 0.000000e+00

S4 7.823043e+05 0.000000e+00

T 6.120000e+11 7.823043e+05 7.823043e+05

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17410382

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档