finding cube root in C++?

后端 未结 12 541
自闭症患者
自闭症患者 2020-12-03 15:18

Strange things happen when i try to find the cube root of a number.

The following code returns me undefined. In cmd : -1.#IND

cout<

        
相关标签:
12条回答
  • 2020-12-03 15:41

    I think you should not confuse exponentiation with the nth-root of a number. See the good old Wikipedia

    0 讨论(0)
  • 2020-12-03 15:42

    pow(x, y) from <cmath> does NOT work if x is negative and y is non-integral.

    This is a limitation of std::pow, as documented in the C standard and on cppreference:

    Error handling

    • Errors are reported as specified in math_errhandling
    • If base is finite and negative and exp is finite and non-integer, a domain error occurs and a range error may occur.
    • If base is zero and exp is zero, a domain error may occur.
    • If base is zero and exp is negative, a domain error or a pole error may occur.

    There are a couple ways around this limitation:

    • Cube-rooting is the same as taking something to the 1/3 power, so you could do std::pow(x, 1/3.).

    • In C++11, you can use std::cbrt. C++11 introduced both square-root and cube-root functions, but no generic n-th root function that overcomes the limitations of std::pow.

    0 讨论(0)
  • 2020-12-03 15:52

    If you ever have no math library you can use this way to compute the cubic root:

    cubic root

    double curt(double x) {
      if (x == 0) {
        // would otherwise return something like 4.257959840008151e-109
        return 0;
      }
      double b = 1; // use any value except 0
      double last_b_1 = 0;
      double last_b_2 = 0;
      while (last_b_1 != b && last_b_2 != b) {
        last_b_1 = b;
        // use (2 * b + x / b / b) / 3 for small numbers, as suggested by  willywonka_dailyblah
        b = (b + x / b / b) / 2;
        last_b_2 = b;
        // use (2 * b + x / b / b) / 3 for small numbers, as suggested by  willywonka_dailyblah
        b = (b + x / b / b) / 2;
      }
      return b;
    }
    

    It is derives from the sqrt algorithm below. The idea is that b and x / b / b bigger and smaller from the cubic root of x. So, the average of both lies closer to the cubic root of x.

    Square Root And Cubic Root (in Python)

    def sqrt_2(a):
        if a == 0:
            return 0
        b = 1
        last_b = 0
        while last_b != b:
            last_b = b
            b = (b + a / b) / 2
        return b
    
    def curt_2(a):
        if a == 0:
            return 0
        b = a
        last_b_1 = 0;
        last_b_2 = 0;
        while (last_b_1 != b and last_b_2 != b):
            last_b_1 = b;
            b = (b + a / b / b) / 2;
            last_b_2 = b;
            b = (b + a / b / b) / 2;
        return b
    

    In contrast to the square root, last_b_1 and last_b_2 are required in the cubic root because b flickers. You can modify these algorithms to compute the fourth root, fifth root and so on.

    Thanks to my math teacher Herr Brenner in 11th grade who told me this algorithm for sqrt.

    Performance

    I tested it on an Arduino with 16mhz clock frequency:

    • 0.3525ms for yourPow
    • 0.3853ms for nth-root
    • 2.3426ms for curt
    0 讨论(0)
  • 2020-12-03 15:56

    Guess you gotta take the negative out and put it in afterwards. You can have a wrapper do this for you if you really want to.

    function yourPow(double x, double y)
    {
        if (x < 0)
            return -1.0 * pow(-1.0*x, y);
        else
            return pow(x, y);
    }
    
    0 讨论(0)
  • 2020-12-03 15:56

    Don't cast to double by using (double), use a double numeric constant instead:

    double thingToCubeRoot = -20.*3.2+30;
    cout<< thingToCubeRoot/fabs(thingToCubeRoot) * pow( fabs(thingToCubeRoot), 1./3. );
    

    Should do the trick!

    Also: don't include <math.h> in C++ projects, but use <cmath> instead.

    Alternatively, use pow from the <complex> header for the reasons stated by buddhabrot

    0 讨论(0)
  • 2020-12-03 15:57

    C++11 has the cbrt function (see for example http://en.cppreference.com/w/cpp/numeric/math/cbrt) so you can write something like

    #include <iostream>
    #include <cmath>
    
    int main(int argc, char* argv[])
    {
       const double arg = 20.0*(-3.2) + 30.0;
       std::cout << cbrt(arg) << "\n";
       std::cout << cbrt(-arg) << "\n";
       return 0;
    }
    

    I do not have access to the C++ standard so I do not know how the negative argument is handled... a test on ideone http://ideone.com/bFlXYs seems to confirm that C++ (gcc-4.8.1) extends the cube root with this rule cbrt(x)=-cbrt(-x) when x<0; for this extension you can see http://mathworld.wolfram.com/CubeRoot.html

    0 讨论(0)
提交回复
热议问题