C ++双值丢失精度乘以?

时间:2010-09-05 02:46:34

标签: c++ algorithm

我正在尝试创建一个函数来查找数字的平方根。出于调试目的,它具有打印当前变量值的指令。函数squareRoot接受两个参数xt。然后它声明并初始化nsn是要添加或减去的数量,每次使用时减半。 s被认为是当前的平方根。运行时,我可以清楚地看到n正在正确调整。但是,当前四位数字正确时,s会停止更改。我在main()中使用此电话:

cout << squareRoot(1000, 10) << "\n";

这应该将1000的平方根打印到最接近的十分之一,但会发生两件奇怪的事情:

  • 它不会停在31.6。
  • 它以4位数停止!

关于它为什么停在四位数的理论是这样的:在乘法中,s会失去一些精度。这是真的?如果是这样,你能告诉我如何纠正它吗?如果不是,导致这种情况的原因以及如何纠正?

我尝试使用另一个变量s1来解决它,它将被乘以并检查。然后s将增加ns1将与s同步。这没用,所以我回到了原始代码。

我的代码如下:

#include <iostream>
using namespace std;

double squareRoot(double x, int t) {
    double s = 0;
    double n = 0.1;
    while ((s*s) <= x) {
            s += n;
            n *= 2;
            cout << n << "\n" << s << "\n";
    }
    cout << "\n";
    s -= n;
    // Keep changing until margin of error is reached
    while ((((s*s) - x) < (1/t)) || ((x - (s*s) < (1/t)))) {
        // If too high, lower s
        if ((s*s) <= x) {
            s += n;
            n /= 2;
            cout << "Adding 1/2 of previous n\n";
        }
        // If too low, raise s
        else if ((s*s) >= x) {
            s -= n;
            n /= 2;
            cout << "Subtracting 1/2 of previous n\n";
        }
        cout << s << "\n" << n << "\n\n";
    }
    return s;
}

我正在运行Windows 7 64位,MSVC ++ 2008 Express。提前感谢您的所有答案!

3 个答案:

答案 0 :(得分:2)

它收敛到正确的平方根,但cout默认只打印六位有效数字:31.xxxx。

另请注意,您的终止检查不起作用,因为对于t> 1,(1 / t)将始终评估为0。请改用1./t。

答案 1 :(得分:1)

原因循环没有停止是循环条件不正确。

while ((current - target < precision) || (target - current < precision)) {
    ...
}

但值current - target或值target - current将为<= 0。并0 < precision。因此,你有相当于while (true) {...}循环 你需要像

这样的东西
while (abs(current - target) > precision) {
    ...
}

(不知道在C ++中获取绝对值的确切函数)

修改
刚刚注意到, hamster3null 在我面前写了1/t

答案 2 :(得分:1)

不相关,但您的sqrt算法可以通过使用现有算法加速,例如Newton's Method。

它是这样的:

double mySqrt(double x, unsigned long accuracy = 10)
{
   if(x < 0.0)
      return(-1.0);

   double retval = 1.0;

   for(unsigned long rep = 0; rep < accuracy; rep++)
      retval = ((x / retval) + retval) / 2.0;

   return(retval);
}

牛顿方法也适用于立方根等。 对于十进制指数,请查找二项式定理。