当我试图找到一个数字的立方根时,奇怪的事情发生了。

以下代码返回未定义的结果。在命令中:-1.#IND

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

虽然这个工作得很好。在命令中:4.93242414866094

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

从数学的角度来看,它一定有效,因为我们可以从负数求立方根。Pow 来自 Visual C++ 2010 math.h 库。有任何想法吗?

有帮助吗?

解决方案

pow(x, y)<cmath> 如果 x 为负且 y 为非整数,则不起作用。

这是一个限制 std::pow, ,如 C 标准和中所述 参考参数:

错误处理

  • 按照 math_errhandling 中的指定报告错误
  • 如果 base 是有限且负的,而 exp 是有限且非整数,则会出现域错误并且可能会出现范围错误。
  • 如果 base 为零且 exp 为零,则可能会出现定义域错误。
  • 如果基数为零且exp为负,则可能会出现域错误或极点错误。

有几种方法可以解决此限制:

  • 立方求根与取某物的 1/3 次方相同,所以你可以这样做 std::pow(x, 1/3.).

  • 在 C++11 中,您可以使用 std::cbrt. 。C++11 引入了平方根和立方根函数,但没有通用的 n 次根函数来克服以下限制: std::pow.

其他提示

在功率1/3是一种特殊情况。在一般情况下,负数的非整数次幂是复杂的。这将是不实际的战俘检查特殊情况下,像整数根,而且,1/3为双不完全是1/3!

我不知道有关Visual C ++战俘,但在错误我的男人网页显示:

  

EDOM的参数x为负且y不是一个整数值。这将导致一个复数。

您将有如果你想负数的立方根用更专业立方根功能 - 或者偷工减料,采取绝对值,再取立方根,然后乘上签回

请注意,根据上下文,负数x1/3功率不一定你期望的负立方根。它可以很容易地成为第一个复杂的根源,x^(1/3) * e^(pi*i/3)。这是惯例Mathematica使用;这也是合理的,只说这是不确定的。

虽然(-1)^ 3 = -1,则不能简单地采取负数的一个合理的功率,并期望一个真实的反应。这是因为有这种理性的指数是在自然界中假想的其他解决方案。结果 HTTP:/ /www.wolframalpha.com/input/?i=x^(1/3),+x+from+-5+to+0

相若方式,标绘X ^ x的。对于x = -1/3,这应该有一个解决方案。然而,这种功能被视为R中未定义对于x <0

因此,不要指望math.h中做魔术,将使其效率低下,你来就可以改变的迹象。

猜你得把负,并把它之后。你可以有一个包装,如果你真的想为你这样做。

function yourPow(double x, double y)
{
    if (x < 0)
        return -1.0 * pow(-1.0*x, y);
    else
        return pow(x, y);
}

不通过使用double投射到(double),使用双数字常量代替:

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

应该做的伎俩!

此外:不包括在C ++项目<math.h>,但使用代替<cmath>

可替换地,从由buddhabrot陈述的pow头的理由使用<complex>

pow( x, y )相同(即,等于)exp( y * log( x ) )

如果日志(x)是无效的,那么POW(X,Y)也是。

同样不能执行0到任何东西的功率,虽然在数学上它应该是0。

C ++ 11具有cbrt功能(参见例如 HTTP:// en.cppreference.com/w/cpp/numeric/math/cbrt ),所以你可以写类似

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

我没有进入C ++标准,所以我不知道该负的参数是如何处理做...上ideone的 http://ideone.com/bFlXYs 似乎证实,C ++(GCC-4.8.1)延伸的立方根与此规则cbrt(x)=-cbrt(-x)x<0;这个扩展可以看到 http://mathworld.wolfram.com/CubeRoot.html

我一直在寻找肘根,发现这个线程,它下面的代码可能工作时对我说:

#include <cmath>
using namespace std;

function double nth-root(double x, double n){
    if (!(n%2) || x<0){
        throw FAILEXCEPTION(); // even root from negative is fail
    }

    bool sign = (x >= 0);

    x = exp(log(abs(x))/n);

    return sign ? x : -x;
}

我觉得你不应该以数字的n次方根混淆幂。看到好的老维基百科

,因为1/3将总是返回0,因为它会被认为是整数... 尝试用1.0 / 3.0 ... 这就是我的想法,但尝试和实施... 不要忘记申报含有1.0和3.0为双变量...

这里有一个小功能,我敲了起来。

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

它使用牛顿 - 拉夫逊找到立方根。

有时牛顿-Raphson卡住,如果根非常接近于0,那么该衍生物可以 得到大,它可以振荡。所以,我已经夹紧,并迫使它重新启动如果出现这种情况。 如果您需要更精确,你可以改变FLT_EPSILONs。

如果你没有数学库,你可以使用这种方法来计算立方根:

立方根

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

它是源自于 sqrt 下面的算法。这个想法是 bx / b / b 从立方根开始变大变小 x. 。因此,两者的平均值更接近于立方根 x.

平方根和三次根(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

与平方根相反, last_b_1last_b_2 因为 b 闪烁,所以需要立方根。您可以修改这些算法来计算四次方根、五次方根等。

感谢我 11 年级的数学老师 Herr Brenner 告诉我这个算法 sqrt.

表现

我在时钟频率为 16mhz 的 Arduino 上进行了测试:

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top