3

我将 math.h 与 GCC 和 GSL 一起使用。我想知道如何评估这个?

我希望 pow 函数将 pow(-1,1.2) 识别为 ((-1)^6)^(1/5)。但事实并非如此。

有人知道可以识别这些的 c++ 库吗?也许有人有一个他们可以分享的分解程序。

4

6 回答 6

12

在数学上,pow(-1, 1.2)根本没有定义。负数的小数指数没有幂,我希望没有库可以简单地为这样的表达式返回一些任意值。你还会期待像这样的事情吗

pow(-1, 0.5) = ((-1)^2)^(1/4) = 1

这显然是不可取的。

此外,浮点数1.2甚至不完全等于6/5. 最接近的双精度数1.2

1.1999999999999999555910790149937383830547332763671875

鉴于此,您现在期望得到什么结果pow(-1, 1.2)

于 2011-06-13T01:02:44.947 回答
9

如果你想提高负数的幂 - 特别是分数幂 - 使用该cpow()方法。您需要包含<complex>才能使用它。

于 2011-06-13T01:03:05.337 回答
3

看来您正在寻找pow(abs(x), y).


解释:你似乎在考虑

x y = (x N ) (y/N)

如果我们选择 N === 2,那么你有

(x 2 ) y/2 = ((x 2 ) 1/2 ) y

(x 2 ) 1/2 = |x|

代入

|x| 是的

这是一个延伸,因为上述操作仅适用于非负 x,但您是选择使用该假设的人。

于 2011-06-13T01:06:49.397 回答
1

听起来您想要执行一个复杂的幂 ( cpow()),然后再取其大小 ( abs())。

>>> abs(cmath.exp(1.2*cmath.log(-1)))
1.0
>>> abs(cmath.exp(1.2*cmath.log(-293.2834)))
913.57662451612202
于 2011-06-13T01:07:20.920 回答
1

pow(a,b)通常被认为、定义和实现为a 的自然对数exp(log(a)*b)在哪里。log(a)log(a) 未定义为 a<=0 的实数。b因此,您需要为负 a 和整数和/或编写具有特殊情况的函数b=1/(some_integer)。integer 的特殊情况很容易b,但b=1/(some_integer)它容易出现舍入问题,就像 Sven Marnach 指出的那样。

也许对于您的域pow(-a,b)应该始终是-pow(a,b)?但是你只需实现这样的功能,所以我认为这个问题需要更多解释。

就像duskwuff 建议的那样,一个更强大和“数学”的解决方案是使用复杂的函数log 和exp,但它比表面上看起来更“复杂”(请原谅我的双关语)(即使有cpow函数)。如果你必须计算很多 pow()s,它会慢得多。

现在有一个重要的问题,可能与您的问题域相关或可能不相关的复数:如果处理得当,结果pow(a,b)不是一个,而是通常是几个复数,但在您关心的情况下,其中一个会是具有几乎为零的虚部的复数(由于舍入错误,它将不为零),您可以简单地忽略和/或不在代码中计算。

为了证明这一点,请考虑是什么pow(-1,.5)。这是一个X这样的数字X^2==-1。你猜怎么着?有 2 个这样的数字:i-i。通常,pow(-1, 1/N)有确切的N解决方案,尽管您只对其中一个感兴趣。

如果所有结果的虚部都很pow(a,b)重要,则意味着您传递了错误的值。对于您描述的范围内的单精度浮点值, 1e-6*max(abs(a),abs(b)) 将是定义“足够显着”阈值的良好起点。极端的“错误值”将pow(-1,0.5)返回0 + 1i0实部,1虚部)。这里的虚部相对于输入和实部来说是巨大的,所以你知道你搞砸了你的输入值。

在任何合理的单返回结果实现中cpow(),cpow(-1,0.3333)可能会返回类似的东西-1+0.000001i并忽略其他两个具有重要虚部的值。因此,您可以获取真正的价值,这就是您的答案。

于 2011-06-13T01:40:58.423 回答
0

使用std::complex. 没有它,统一的根源就没有多大意义。有了它,它们就很有意义。

于 2011-06-13T01:08:18.363 回答