为什么这段代码不计算负数的立方根?

Why does this code not do cube roots of negative numbers?

我正在用 C 语言编写一个函数来计算数字的根,我偶然发现了一个问题:它对正数的立方根和平方根非常有效,但是当我尝试计算立方根时一个负数,它 returns: -1.#IND00 我试着研究了一下,结果发现返回的数字太大了,但我不明白为什么…… ('rooter' 是函数,x 是基数,ind 是度数。)

我也尝试输入“0.66”而不是 1/ind,但结果相同。

float rooter(int x, int ind)
{
    if(ind%2==0)
    {
        if (x>=0)
            return ( pow(x, 1.0/ind) );
        else
            errore=1;
        return -1;
    }
    else
    {
        return ( pow(x, (float)1.0/ind) );
    }
}

pow 不接受非整数指数的负底数。 (可能是因为在传统定义的特殊情况下工作太麻烦了,尤其是当它需要使用对数来实现时。)

正如 AProgrammer 所述,pow 函数在您的情况下不接受否定 x。要解决这个问题,您可以 'remember' x 的符号,将其 positive 值(幅度)传递给 pow,然后重新应用符号(因为您已经检查过 ind 在这种情况下是奇数):

else {
    float sign = x < 0.0 ? -1.0 : +1.0;
//  return sign * ( pow(fabs(x), (float)1.0/ind) ); // MNC - see comments
    return sign * ( pow(fabs(x), 1.0/ind) );        // BPC - maybe?
}

随时要求进一步澄清and/or解释。

pow 必须 return 复数才能处理负数而不需要更复杂的 API。他们的方法快速、易于使用且易于访问。只有一个简单的规则:基数必须为零或正数^^

另外,为什么强制转换为浮动?

只需将代码更改为

else
{
    return pow(fabs(x), 1.0 / ind) * (x < 0 ? -1 : 1);
}

这个答案比目前为止的其他答案更具哲理,并试图解决根本问题 "why doesn't pow allow a negative base with a float exponent?".

考虑浮点数的工作原理以及有理数的幂是如何定义的。现在给定一个负底,问问自己有理指数是多少结果是实数?

使用通常的数学定义 (-2)^(1/2) 不是实数,但您可以找到任意接近 1/2 的值。例如 (-2)^(49999/99999) 是真实的。这意味着,如果实现试图确定什么是真实的,什么不是真实的,那么任何浮点精度错误实际上可能会将您的表达式从实数交换为虚数,反之亦然,这从程序员的角度来看是不稳定的。

此类定义的另一个问题是它要求我们以最简化的形式表示有理指数以确定表达式是否为实数。这通常不是一个简单的表示来确定。请注意 (-2)^(2/4) 是虚数,即使 -2 平方的四次方根是实数。