math.acos acos范围内的数学域错误

math.acos math domain error within the range of acos

我有一个脚本可以 运行 通过一组三角形的坐标来确定它们是否是直角三角形。其中一部分使用了余弦规则,我在检查恰好落在一条直线上的一组特定点时遇到了一个问题。这是导致问题的部分:

s1 = math.sqrt(((x2-x1)**2)+((y2-y1)**2))
s2 = math.sqrt(((x3-x2)**2)+((y3-y2)**2))
s3 = math.sqrt(((x3-x1)**2)+((y3-y1)**2))
num1 = (s1**2)+(s2**2)-(s3**2)
den1 = (2)*(s1)*(s2)
theta1 = math.acos(num1/den1)
num2 = (s1**2)+(s3**2)-(s2**2)
den2 = (2)*(s1)*(s3)
theta2 = math.acos(num2/den2)
num3 = (s3**2)+(s2**2)-(s1**2)
den3 = (2)*(s3)*(s2)
theta3 = math.acos(num3/den3)

当我运行通过三个点([0,0],[4,4],[1,1])时,我得到以下错误:

Traceback (most recent call last):
File "./i091.py", line 79, in <module>
    detect_right_triangle(xy1, xy2, xy3)
File "./i091.py", line 50, in detect_right_triangle
    theta2 = math.acos(num2/den2)
ValueError: math domain error

为了确保我没有超出余弦函数的范围,我让它打印了所有评估点的 theta2 的分子和分母,并得到了这个点问题:

***** [[0, 0], [4, 2], [1, 1]]
>>> num2 =  12.0
>>> den2 =  12.6491106407
***** [[0, 0], [4, 3], [1, 1]]
>>> num2 =  14.0
>>> den2 =  14.1421356237
***** [[0, 0], [4, 4], [1, 1]]
>>> num2 =  16.0
>>> den2 =  16.0

我原以为无论出于何种原因 (16.0) 将两个相同的数字相除会出现问题,但第二点在 [2,2] 和 [3,3] 上效果很好:

***** [[0, 0], [2, 2], [1, 1]]
>>> num2 =  8.0
>>> den2 =  8.0

...

***** [[0, 0], [3, 3], [1, 1]]
>>> num2 =  12.0
>>> den2 =  12.0

想知道这里可能出了什么问题吗?

当我运行你的代码:

import math

def foo(x, y):
    x1, x2, x3 = x
    y1, y2, y3 = y
    s1 = math.sqrt(((x2-x1)**2)+((y2-y1)**2))
    s2 = math.sqrt(((x3-x2)**2)+((y3-y2)**2))
    s3 = math.sqrt(((x3-x1)**2)+((y3-y1)**2))
    num1 = (s1**2)+(s2**2)-(s3**2)
    den1 = (2)*(s1)*(s2)
    theta1 = math.acos(num1/den1)
    num2 = (s1**2)+(s3**2)-(s2**2)
    den2 = (2)*(s1)*(s3)
    print repr(num2), repr(den2)
    print repr(num2 / den2)
    theta2 = math.acos(num2/den2)
    num3 = (s3**2)+(s2**2)-(s1**2)
    den3 = (2)*(s3)*(s2)
    theta3 = math.acos(num3/den3)

foo([0, 4, 1], [0, 4, 1])

我明白了 num2/den2 == 1.0000000000000004。除非您打印出完整的精度,否则您可能不会注意到 num2den2 略大 ,这导致值略大于 1。显然,因为余弦的最大值是 1,所以你不能取比 1 大的数的 arcos。