我发现了C中log
函数的一个奇怪行为,并且对log
函数处理复数无穷数的行为感到困惑。具体来说,当我期望(inf + nan * 1j)
时,log(inf + inf * 1j)
等于(inf + 0.785398j)
。
取复数的对数时,真实的部是输入绝对值的对数,虚部是输入的相位。返回0.785398作为log(inf + inf * 1j)
的虚部意味着它假设实部和虚部中的inf
具有相同的长度。这个假设似乎与其他计算不一致,例如,inf - inf == nan
、inf / inf == nan
(假设2 × inf
)不必具有相同的值。
为什么log(inf + inf * 1j)
的假设不同?
复制C代码:
#include <complex>
#include <limits>
#include <iostream>
int main() {
double inf = std::numeric_limits<double>::infinity();
std::complex<double> b(inf, inf);
std::complex<double> c = std::log(b);
std::cout << c << "\n";
}
复制Python代码(numpy):
import numpy as np
a = complex(float('inf'), float('inf'))
print(np.log(a))
2条答案
按热度按时间sh7euo9m1#
free final draft of the C99 specification在第491页上说
clog(+∞,+i∞)返回+∞ + iπ/4。
currently仍然是这种情况。C++ specification使用注解解释了相同的规则
此函数的语义旨在与C函数
clog
保持一致。我同意这种行为从数学的Angular 看是令人困惑的,并且可以说与其他
inf
语义不一致,正如你指出的,但是实际上,它是C标准的一部分,这使得它成为C++标准的一部分,并且由于NumPy通常依赖于C行为(即使在令人困惑的情况下),这在Python示例中是继承的。标准库
cmath.log()
函数具有相同的行为(if you test it right...):我没有办法研究C标准的基本原理,我假设这里有实用的选择,可能是在考虑这些复杂的函数如何相互作用时。
q8l4jmvw2#
值0.785398(实际上是pi/4)至少与 * 一些 * 其他函数一致:正如你所说,复数的对数的虚部等于该数的相角。2这可以转化为一个问题:
inf + j * inf
的相位角是多少?我们可以通过
atan2(Im(z), Re(z))
计算复数z
的相位角,对于给定的数字,这可以归结为计算atan2(inf, inf)
,对于Numpy和C/C++,atan2(inf, inf)
也是0.785398(或pi/4),所以现在可以问一个类似的问题:为什么是atan2(inf, inf) = 0.785398
?对于后者,我没有答案(除了“C/C++规范是这么说的”,其他人已经回答了),我只有一个猜测:如
atan2(y, x) == atan(y / x)
对x > 0
,可能有人在此上下文中决定不将inf / inf
解释为“未定义”,而是解释为“一个非常大的数除以同一个非常大的数”。此比率的结果将是1,并且根据atan
的数学定义,atan(1) == pi/4
为atan
。也许这不是一个令人满意的答案,但至少我可以有希望地表明,给定边缘情况下的
log
定义与相关函数定义的类似边缘情况并非完全不一致。编辑:正如我所说,与 * 一些 * 其他函数一致:例如,它也与
np.angle(complex(np.inf, np.inf)) == 0.785398
一致。