finding cube root in C++?

2019-02-09 00:33发布

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<<pow(( double )(20.0*(-3.2) + 30.0),( double )1/3)

While this one works perfectly fine. In cmd : 4.93242414866094

cout<<pow(( double )(20.0*4.5 + 30.0),( double )1/3)

From mathematical way it must work since we can have the cube root from a negative number. Pow is from Visual C++ 2010 math.h library. Any ideas?

标签: c++ math.h pow
12条回答
再贱就再见
2楼-- · 2019-02-09 01:13

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

查看更多
Summer. ? 凉城
3楼-- · 2019-02-09 01:14

The power 1/3 is a special case. In general, non-integral powers of negative numbers are complex. It wouldn't be practical for pow to check for special cases like integer roots, and besides, 1/3 as a double is not exactly 1/3!

I don't know about the visual C++ pow, but my man page says under errors:

EDOM The argument x is negative and y is not an integral value. This would result in a complex number.

You'll have to use a more specialized cube root function if you want cube roots of negative numbers - or cut corners and take absolute value, then take cube root, then multiply the sign back on.

Note that depending on context, a negative number x to the 1/3 power is not necessarily the negative cube root you're expecting. It could just as easily be the first complex root, x^(1/3) * e^(pi*i/3). This is the convention mathematica uses; it's also reasonable to just say it's undefined.

查看更多
我命由我不由天
4楼-- · 2019-02-09 01:14

pow( x, y ) is the same as (i.e. equivalent to) exp( y * log( x ) )

if log(x) is invalid then pow(x,y) is also.

Similarly you cannot perform 0 to the power of anything, although mathematically it should be 0.

查看更多
Fickle 薄情
5楼-- · 2019-02-09 01:14

Here's a little function I knocked up.

#define uniform() (rand()/(1.0 + RAND_MAX))

double CBRT(double Z)
{
    double guess = Z;
    double x, dx;
    int loopbreaker;

retry:
    x = guess * guess * guess;
    loopbreaker = 0;
    while (fabs(x - Z) > FLT_EPSILON)
    {
        dx = 3 * guess*guess;
        loopbreaker++;
        if (fabs(dx) < DBL_EPSILON || loopbreaker > 53)
        {
            guess += uniform() * 2 - 1.0;
            goto retry;
        }
        guess -= (x - Z) / dx;
        x = guess*guess*guess;
    }

    return guess;
}

It uses Newton-Raphson to find a cube root.

Sometime Newton -Raphson gets stuck, if the root is very close to 0 then the derivative can get large and it can oscillate. So I've clamped and forced it to restart if that happens. If you need more accuracy you can change the FLT_EPSILONs.

查看更多
劳资没心,怎么记你
6楼-- · 2019-02-09 01:17

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.

查看更多
Explosion°爆炸
7楼-- · 2019-02-09 01:17

While (-1)^3 = -1, you can't simply take a rational power of a negative number and expect a real response. This is because there are other solutions to this rational exponent that are imaginary in nature.
http://www.wolframalpha.com/input/?i=x^(1/3),+x+from+-5+to+0

Similarily, plot x^x. For x = -1/3, this should have a solution. However, this function is deemed undefined in R for x < 0.

Therefore, don't expect math.h to do magic that would make it inefficient, just change the signs yourself.

查看更多
登录 后发表回答