使用 NumPy 评估三角恒等式时的惊人差异

计算科学 Python 数字
2021-12-16 09:30:46

根据 Wolfram Alpha 和Sage 计算机代数系统,以下恒等式成立:

cos(arctan(l1l2d))=11+(l1l2)2d2

但是,当我尝试用 NumPy 中的任意示例验证它时,我注意到同一性两边计算的实际值存在相当大的差异。我使用了以下代码:

    l1 = 10; l2 = 8; d = 17
    from numpy import arctan2, cos, sin, sqrt

    alpha = arctan2((l1-l2),d)
    left = cos(alpha)

    right = sqrt(1 + ((l1-l2)**2)/(d**2))

评估结果leftright得出以下结果:

    left = 0.99315060432287616
    right = 1.0

很容易将其简单地视为一个数值错误,但由于我对数值错误会产生多大的经验很少,所以我不太确定。这是可能的还是我错过了什么(很明显)?

2个回答

我怀疑您右侧的 Python 表达式正在执行整数除法,而不是浮点除法。结果,((l1-l2)**2)/(d**2)被评估为零,平方根内的项为一。

事实上,你也忘记了右手表达式中的倒数,但这不是第一个问题......

在 MATLAB 中:

>> l1 = 10; l2 = 8; d = 17;
>> alpha = atan2((l1-l2),d)
alpha =
    0.1171
>> left = cos(alpha)
left =
    0.9932
>> right = 1/sqrt(1 + ((l1-l2)^2)/(d^2))
right =
    0.9932

正如 Michael C. Grant 所指出的,问题在于除法运算是整数除法,而不是浮点除法。在 Python 3 之前的版本中,使用/向下舍入将两个整数除以整数。可以通过添加来更改此行为

from __future__ import division

在脚本的顶部。请注意,此声明/仅更改当前文件的行为。如果您偶尔想要原始行为,请使用//(双斜杠)。此处将对此进行更详细的讨论:

PEP 238 -- 更改除法运算符

请注意,尽管包括 C 在内的大多数语言都具有相似的除法语义,但 Python 中的语义更加混乱,因为整数在传递给函数时通常不会被提升为浮点数。因此,一个写得好像它是在浮点数上操作的函数实际上可能是在整数上操作。