为什么在C++中,(0+0i)^{0}等于(nan, nan)?

10

看一下下面的代码:

#include <complex>
#include <iostream>

int main()
{
    std::cout << std::pow( std::complex<double>(0,0), std::complex<double>(0,0) ) << "\n";
    std::cout << std::pow( std::complex<double>(0,0), double(0) ) << "\n";

    return 0;
}

使用g++(4.8.1)编译的输出结果为

(nan,nan)
(-nan,-nan)

当使用clang++(3.3)编译时,会输出:

(-nan,-nan)
(-nan,-nan)

但是我期望的是(1.0, 0.0)。

有人能给出解释吗?


@Mr.Alien:确实如此,我不明白他为什么会有那样的期望。 - PlasmaHH
@PlasmaHH这就是他在问的原因 :) - Mr. Alien
3
“零”除以“零”是未定义的:http://www.math.utah.edu/~pa/math/0to0.html - Shafik Yaghmour
@Mr.Alien:我认为他不是在问为什么他期望得到1.0、0.0... - PlasmaHH
数学上应该是(1,0),但为什么g ++ / clang ++在此处给出(nan,nan)- 这就是问题所在。 - Feng Wang
2个回答

6
根据 std::pow 文档

返回值
底数的指数幂 (exp 或 iexp)。
如果底数为0且指数小于或等于​0​,则会出现域错误。在这种情况下返回NAN。 [...]

在您的代码中,既有底数为0且指数等于0的情况,因为复数 0 + 0 *i 仍然是0。因此,预计会出现 NaN
根据 @Fred Larson 的提供的信息,并根据重载的 std::pow for std::complex

计算将复数 x 提高到复数幂 y。该操作定义为 exp(y · log(x) )。负实轴上存在分支切割。 pow(0, 0) 的结果由实现定义。


1
其实,我不确定引用是相关的,因为pow()已被覆盖为std::complex。但这个链接是相关的:http://en.cppreference.com/w/cpp/numeric/complex/pow 值得注意的是,“pow(0, 0)的结果是由实现定义的。” - Fred Larson
@FredLarson 这可能解释了为什么Visual Studio会给出(1,0)(1,0)的结果? - Floris Velleman
@FlorisVelleman:听起来它可以返回任何想要的东西。 - Fred Larson
在发布之前,我已经阅读了C++标准草案N3376,但没有找到这个问题;非常感谢。 - Feng Wang

4

正如Fred Larson所指出的那样,文档中写道:

pow(0, 0)的结果是实现定义的。

从数学上讲,这是有道理的,因为我们有一个矛盾的情况,其中N^0应该始终为1,但0^N对于N > 0应该始终为0,因此您在数学上对此结果没有期望。这个Wolfram Alpha论坛帖子详细介绍了一些内容。

当复数的虚部不为零时,这种情况被称为更加复杂。如果 x 是实数,则 x^y 应该是未定义的,但是如果 x 有一个虚部分量,那么它看起来就不再是未定义的了。

在Python中也有吗?你检查了吗? - Grijesh Chauhan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接