2012-11-30 50 views
5

我寫了一個名爲analyze_the_shape的函數,它取得了一個2D頂點列表,使得該列表按照二維歐幾里德空間中頂點的順時針遍歷順序排列。爲什麼我會得到ValueError:數學域錯誤?

我在口譯員稱它爲[(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 

回答

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 。如果我在行angle = math.degrees(math.acos(cos_angle))之前打印出cos_angle < -1.0,則會打印True。如果我打印出cos_angle,它會打印-1.0

我猜這裏的問題是,Python存儲cos_angle的方式並不完美,並且您爲cos_angle生成的值僅略小於-1.0

也許它會更好,如果不是檢查abs(angle - 90.0) < 0.001,而是檢查是否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中減去該數量。

+0

'abs(angle-90.0)<0.001'和'abs(cos_angle + 1)<0.001'並不意味着相同。如果'angle = 90','cos_angle = 0'。如果'cos_angle = -1','angle = 180'。 –

+0

好趕上!我認爲在OP設置「cos_angle」時出現錯誤 - 我在回答中指出了這一點。 –

+0

「Python存儲'cos_angle'的方式並不完美」。這應該是「在計算機上表示浮點數的方式並不完美,因此計算錯誤是不可避免的」。 Python與此完全無關。 – Bakuriu

8

此例外意味着cos_angle不是math.acos的有效參數。

具體而言,在本例中,它正好低於-1,這是在acos定義之外。

你也許可以嘗試強迫你返回內[-1,1]cos_angle的東西,如:

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

但是,這將不會返回SQUARE,因爲cos_angle或多或少等於-1在你的榜樣,並angle從而等於180。在例外之前,您的計算可能存在問題。

0

嘗試舍入cos_angle。我有同樣的問題;在我的腳本中,math.acos(x)中的x的值出現爲-1.0000000000000002。爲了解決它,我只是將x的值舍入到小數點後六位,所以它出現到-1.0。

2

我有同樣的問題,事實證明@crld是正確的。 我的輸入值應該是在範圍[-1,1],但是......

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

所以,作爲一般規則,我建議所有四捨五入你送入math.acos彩車。

相關問題