我将 math.h 与 GCC 和 GSL 一起使用。我想知道如何评估这个?
我希望 pow 函数将 pow(-1,1.2) 识别为 ((-1)^6)^(1/5)。但事实并非如此。
有人知道可以识别这些的 c++ 库吗?也许有人有一个他们可以分享的分解程序。
我将 math.h 与 GCC 和 GSL 一起使用。我想知道如何评估这个?
我希望 pow 函数将 pow(-1,1.2) 识别为 ((-1)^6)^(1/5)。但事实并非如此。
有人知道可以识别这些的 c++ 库吗?也许有人有一个他们可以分享的分解程序。
在数学上,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)
?
如果你想提高负数的幂 - 特别是分数幂 - 使用该cpow()
方法。您需要包含<complex>
才能使用它。
看来您正在寻找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,但您是选择使用该假设的人。
听起来您想要执行一个复杂的幂 ( cpow()
),然后再取其大小 ( abs()
)。
>>> abs(cmath.exp(1.2*cmath.log(-1)))
1.0
>>> abs(cmath.exp(1.2*cmath.log(-293.2834)))
913.57662451612202
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 + 1i
(0
实部,1
虚部)。这里的虚部相对于输入和实部来说是巨大的,所以你知道你搞砸了你的输入值。
在任何合理的单返回结果实现中cpow()
,cpow(-1,0.3333)
可能会返回类似的东西-1+0.000001i
并忽略其他两个具有重要虚部的值。因此,您可以获取真正的价值,这就是您的答案。
使用std::complex
. 没有它,统一的根源就没有多大意义。有了它,它们就很有意义。