代码之家  ›  专栏  ›  技术社区  ›  masonsbro

C++双值乘法时丢失精度?

  •  1
  • masonsbro  · 技术社区  · 16 年前

    我试图创建一个函数来求一个数的平方根。出于调试目的,它有打印当前变量值的指令。函数 squareRoot x 和 t n 和 s . n 是要加或减的量,每次使用时减半。 s 是当前的平方根。跑步时,我能清楚地看到 n 前四位数正确时停止更改。我在用这个电话 main()

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

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

    • 它不会停在31.6。

    我的理论是:在乘法中, 失去了一些精确性。这是真的吗?如果是的话,你能告诉我怎么改正吗?如果不是,是什么原因造成的,我如何纠正?

    我已经试着用另一个变量来解决了, s1 s 将增加 n ,和 s1级 与同步 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;
    }
    

    3 回复  |  直到 16 年前
        1
  •  1
  •   Mateen Ulhaq    14 年前

    不相关,但是通过使用现有的sqrt算法(如牛顿法),可以加快sqrt算法的速度。

    它是这样的:

    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);
    }
    

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

        2
  •  2
  •   Eugene Smith    16 年前

    它收敛到正确的平方根,但在默认情况下只能打印六个有效数字:31.xxxx。

    另请注意,终止检查不起作用,因为对于t>1,(1/t)将始终计算为0。用1./t代替。

        3
  •  1
  •   Nikita Rybak    16 年前

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

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

    current - target 或价值 target - current 将 <= 0 0 < precision . 所以你有相当于 while (true) {...} 循环。

    while (abs(current - target) > precision) {
        ...
    }
    

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

    编辑
    刚注意到, 仓鼠3 1/t 在我面前。