7

我写了一个名为的函数analyze_the_shape,它接受一个二维顶点列表,使得该列表按照顺时针遍历二维欧几里得空间中的顶点的顺序排列。

我在解释器中调用它并[(0, 0), (0, 4.0), (4.0, 4.0), (4.0, 0)]作为输入给出,但我得到ValueError : math domain error. 我期待看到return ["SQUARE", 4.0]。我能做些什么 ?

import math

def analyze_the_shape(liste):
    if len(liste) == 2 :
        d = ( (liste[1][0] - liste[0][0])**2 + (liste[1][1] - liste[0][1])**2 )**(0.5)   
        return ["LINESEGMENT", d ] 
    if len(liste) == 4 :
        d1 = abs(( (liste[1][0] - liste[0][0])**2 + (liste[1][1] - liste[0][1])**2 )**(0.5))
        d2 = abs(( (liste[2][0] - liste[1][0])**2 + (liste[2][1] - liste[1][1])**2 )**(0.5))
        d3 = abs(( (liste[3][0] - liste[2][0])**2 + (liste[3][1] - liste[2][1])**2 )**(0.5))
        d4 = abs(( (liste[0][0] - liste[3][0])**2 + (liste[0][1] - liste[3][1])**2 )**(0.5)) 
        hypo = abs(( (liste[2][1] - liste[0][1])**2 + (liste[2][0] - liste[0][0])**2 )**(0.5))
        cos_angle = float((hypo**2 - (d3)**2 + (d4)**2) / ((-2.0)*(d4)*(d3)))
        angle = math.degrees(math.acos(cos_angle))
        if d1 == d2 == d3 == d4 and abs(angle - 90.0) < 0.001 :
            return ["SQUARE", d1]  

这是我得到的错误:

>>> import a
>>> a.analyze_the_shape([(0, 0), (0, 4.0), (4.0, 4.0), (4.0, 0)])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "a.py", line 15, in analyze_the_shape

ValueError: math domain error
4

4 回答 4

9

此异常意味着cos_angle不是 的有效参数math.acos

具体来说,在这个例子中,它刚好低于 -1,这是超出acos定义的。

您可能会尝试通过以下方式强制您返回cos_angle内部[-1,1]

def clean_cos(cos_angle):
    return min(1,max(cos_angle,-1))

但是,这不会返回SQUARE,因为在您的示例中cos_angle或多或少等于,因此等于。在异常发生之前,您的计算可能存在问题。-1angle180

于 2012-11-30T01:05:28.793 回答
3

我遇到了同样的问题,结果证明@crld 是对的。我的输入值应该在 [-1, 1] 范围内,但是...

print('{0:.32f}'.format(x))
>> 1.00000000000000022204460492503131

因此,作为一般规则,我建议将您输入的所有浮点数四舍五入math.acos

于 2017-05-08T19:01:34.357 回答
1

当我运行您的代码时,我得到的堆栈跟踪是:

Traceback (most recent call last):
  File "md.py", line 22, in <module>
    analyze_the_shape([(0, 0), (0, 4.0), (4.0, 4.0), (4.0, 0)])
  File "md.py", line 18, in analyze_the_shape
    angle = math.degrees(math.acos(cos_angle))
ValueError: math domain error

我知道math.acos只接受这样的值-1.0 <= x <= 1.0。如果我cos_angle < -1.0在该行之前打印出来angle = math.degrees(math.acos(cos_angle)),它会打印出来True。如果我打印出来cos_angle,它就会打印出来-1.0

我猜这里的问题是 Python 存储的方式cos_angle并不完美,并且您生成的值cos_angle仅略低于-1.0.

abs(angle - 90.0) < 0.001如果您检查 if而不是检查,也许会更好abs(cos_angle) < 0.001

编辑

我认为你在这一行有一个错误:

cos_angle = float((hypo**2 - (d3)**2 + (d4)**2) / ((-2.0)*(d4)*(d3)))

大概应该是:

cos_angle = float((hypo**2 - ((d3)**2 + (d4)**2)) / ((-2.0)*(d4)*(d3)))

注意周围的额外括号(d3)**2 + (d4)**2。这可确保在您从 中减去该数量之前hypo**2完成加法。

于 2012-11-30T00:59:43.320 回答
0

尝试四舍五入 cos_angle。我有同样的问题;在我的脚本中,x in 的值是 math.acos(x)-1.0000000000000002。为了解决这个问题,我只是将 x 的值四舍五入到小数点后六位,所以结果是 -1.0。

于 2016-04-18T17:17:57.723 回答