当我试图找到数字的立方根时,会发生奇怪的事情。
以下代码返回undefined undefined。在cmd:-1。#IND
cout<<pow(( double )(20.0*(-3.2) + 30.0),( double )1/3)
虽然这个很好用。在cmd:4.93242414866094
cout<<pow(( double )(20.0*4.5 + 30.0),( double )1/3)
从数学方面来看,它必须有效,因为我们可以从负数中得到立方根。 Pow来自Visual C ++ 2010 math.h库。有什么想法吗?
答案 0 :(得分:15)
pow(x, y)
的{p> <cmath>
不起作用。
这是std::pow
的限制,如C标准和cppreference中所述:
错误处理
- 按照math_errhandling
中的规定报告错误- 如果base为有限且为负且exp为有限且非整数,则会发生域错误并可能发生范围错误。
- 如果base为零且exp为零,则可能发生域错误。
- 如果base为零且exp为负数,则可能会出现域错误或极点错误。
这种限制有几种方法:
立方体生根与取得1/3功率相同,因此您可以std::pow(x, 1/3.)
。
在C ++ 11中,您可以使用std::cbrt
。 C ++ 11引入了平方根和立方根函数,但没有通用的第n个根函数来克服std::pow
的限制。
答案 1 :(得分:8)
权力1/3
是一种特殊情况。通常,负数的非整数幂是复杂的。对于pow来检查像整数根这样的特殊情况是不切实际的,此外,1/3
作为双精度并不完全是1/3!
我不知道visual C ++ pow,但是我的man page在错误中说:
EDOM
参数x
为负数,y
不是整数值。这会导致数字复杂。
如果你想要负数的立方根 - 或者削减角落并取绝对值,你需要使用一个更专业的立方根函数,然后取立方根,然后重新加上符号。
请注意,根据上下文,x
幂的负数1/3
不一定是您期望的负立方根。它可以很容易地成为第一个复杂的根x^(1/3) * e^(pi*i/3)
。这是mathematica使用的惯例;只是说它未定义也是合理的。
答案 2 :(得分:7)
当(-1)^ 3 = -1时,你不能简单地采用负数的理性幂并期望得到真实的反应。这是因为这个理性指数的其他解决方案本质上是虚构的 http://www.wolframalpha.com/input/?i=x^(1/3),+x+from+-5+to+0
同样地,绘制x ^ x。对于x = -1/3,这应该有一个解决方案。但是,对于x 因此,不要指望math.h做一些会使效率低下的魔法,只需自己更改标志。
答案 3 :(得分:3)
猜猜你必须把消极的东西拿出去然后把它放进去。如果您真的想要,可以让包装器为您执行此操作。
function yourPow(double x, double y)
{
if (x < 0)
return -1.0 * pow(-1.0*x, y);
else
return pow(x, y);
}
答案 4 :(得分:2)
请勿使用double
转换为(double)
,而是使用双倍数字常量:
double thingToCubeRoot = -20.*3.2+30;
cout<< thingToCubeRoot/fabs(thingToCubeRoot) * pow( fabs(thingToCubeRoot), 1./3. );
应该做的伎俩!
另外:不要在C ++项目中包含<math.h>
,而是使用<cmath>
。
或者,根据buddhabrot所述的原因,使用pow
标题中的<complex>
答案 5 :(得分:2)
pow( x, y )
与exp( y * log( x ) )
如果log(x)无效,那么pow(x,y)也是。
同样地,你不能对任何东西的力量执行0,虽然在数学上它应该是0。
答案 6 :(得分:2)
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
答案 7 :(得分:1)
我正在寻找cubit root并找到了这个帖子,我觉得以下代码可能有效:
#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;
}
答案 8 :(得分:0)
我认为你不应该将取幂与数字的第n个根混淆。查看好的旧Wikipedia
答案 9 :(得分:0)
因为1/3将始终返回0,因为它将被视为整数... 试试1.0 / 3.0 ...... 这是我的想法,但尝试和实施...... 并且不要忘记将包含1.0和3.0的变量声明为double ...
答案 10 :(得分: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;
}
它使用Newton-Raphson来查找立方根。
有时Newton -Raphson会被卡住,如果根非常接近于0那么导数就可以了 变大,它可以振荡。因此,如果发生这种情况,我已将其限制并强制重启。 如果您需要更高的准确度,可以更改FLT_EPSILON。
答案 11 :(得分:0)
如果您没有数学库,可以使用这种方式计算立方根:
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
算法。我们的想法是b
和x / b / b
从x
的立方根更大更小。因此,两者的平均值更接近x
的立方根。
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_1
和last_b_2
,因为b闪烁。您可以修改这些算法以计算第四个根,第五个根等等。
感谢我11年级的数学老师Herr Brenner,他告诉我sqrt
的算法。
我在16mhz时钟频率的Arduino上进行了测试: