2017-09-17 420 views
-1

我正嘗試使用python創建一個簡單的模擬退火搜索,但在使用math.exp計算指數時總是顯示溢出錯誤。OverflowError:數學範圍錯誤 - 指數Python

,這是我在Python代碼:

import random 
import math 

def getF(x1, x2): 
    t1 = (4 - (2.1 * (x1 ** 2) + (x1 ** 4)/3)) * (x1 ** 2) 
    t2 = x1 * x2 
    t3 = (-4 + (4 * (x2 ** 2))) * (x2 ** 2) 
    t = t1 + t2 + t3 
    return t 


def getP(dE, t): 
    return math.exp((-1*dE)/t) 


def getNewRandInRange(x): 
    newX = x + random.randint(-5, 5) 
    while (newX > 10) or (newX < -10): 
     newX = x + random.randint(-5, 5) 
    return newX 

initState1 = random.randint(-10, 10) 
initState2 = random.randint(-10, 10) 

currentState1 = initState1 
currentState2 = initState2 

BSF = getF(currentState1, currentState2) 

T = 1000 
Tmin = 1 

while T > Tmin: 
    print("T= %f" %T) 
    newState1 = getNewRandInRange(currentState1) 
    newState2 = getNewRandInRange(currentState2) 

    currentF = getF(currentState1, currentState2) 
    newF = getF(newState1, newState2) 

    print("Current X1= %f" % currentState1) 
    print("Current X2= %f" % currentState2) 
    print("New X1= %f" % newState1) 
    print("New X2= %f" % newState2) 

    dE = currentF - newF 
    print ("delta E: %f" %dE) 

    if dE > 0: 
     currentState1 = newState1 
     currentState2 = newState2 
     BSF = getF(newState1, newState2) 
    else: 
     randNumber = random.uniform(0, 1) 
     p = getP(dE, T) 
     if (randNumber < p): 
      currentState1 = newState1 
      currentState2 = newState2 

    print("BSF: %f" %BSF) 
    print("\n\n\n") 
    T = T * 0.9 

print(BSF) #final output 

錯誤信息:

Traceback (most recent call last): 
    return math.exp((-1*dE)/t) 
OverflowError: math range error 

我使用try和catch嘗試,但它不會返回的階數,它會使得結果的問題,我也試着用google搜索,但沒有找到任何符合我要求的解決方案。

謝謝!

+0

可能你也發佈了錯誤追蹤記錄 –

+0

你可以檢查( - 1 * dE)/ t,他們可能會非常大或很小 –

回答

0

exception OverflowError

當算術運算的結果太大而無法表示時引發。對於長整數(這會引發MemoryError而不是放棄)以及對於大多數使用普通整數的操作(它們會返回長整數)不會發生這種情況。由於C中缺少浮點異常處理的標準化,大多數浮點操作也不會被檢查。 Ref

您試圖計算一個大數字(大於710),並且超出了double範圍。

你可以try/except這樣的處理:

def getP(dE, t): 
    try: 
     return math.exp((-1*dE)/t) 
    except: 
     return -1 # or anything else :D 

你可以在Python的代碼此評論:

/* 
* For the sake of simplicity and correctness, we impose an artificial 
* limit on ndigits, the total number of hex digits in the coefficient 
* The limit is chosen to ensure that, writing exp for the exponent, 
* 
* (1) if exp > LONG_MAX/2 then the value of the hex string is 
* guaranteed to overflow (provided it's nonzero) 
* 
* (2) if exp < LONG_MIN/2 then the value of the hex string is 
* guaranteed to underflow to 0. 
* 
* (3) if LONG_MIN/2 <= exp <= LONG_MAX/2 then there's no danger of 
* overflow in the calculation of exp and top_exp below. 
* 
* More specifically, ndigits is assumed to satisfy the following 
* inequalities: 
* 
* 4*ndigits <= DBL_MIN_EXP - DBL_MANT_DIG - LONG_MIN/2 
* 4*ndigits <= LONG_MAX/2 + 1 - DBL_MAX_EXP 
* 
* If either of these inequalities is not satisfied, a ValueError is 
* raised. Otherwise, write x for the value of the hex string, and 
* assume x is nonzero. Then 
* 
* 2**(exp-4*ndigits) <= |x| < 2**(exp+4*ndigits). 
* 
* Now if exp > LONG_MAX/2 then: 
* 
* exp - 4*ndigits >= LONG_MAX/2 + 1 - (LONG_MAX/2 + 1 - DBL_MAX_EXP) 
*     = DBL_MAX_EXP 
* 
* so |x| >= 2**DBL_MAX_EXP, which is too large to be stored in C 
* double, so overflows. If exp < LONG_MIN/2, then 
* 
* exp + 4*ndigits <= LONG_MIN/2 - 1 + (
*      DBL_MIN_EXP - DBL_MANT_DIG - LONG_MIN/2) 
*     = DBL_MIN_EXP - DBL_MANT_DIG - 1 
* 
* and so |x| < 2**(DBL_MIN_EXP-DBL_MANT_DIG-1), hence underflows to 0 
* when converted to a C double. 
* 
* It's easy to show that if LONG_MIN/2 <= exp <= LONG_MAX/2 then both 
* exp+4*ndigits and exp-4*ndigits are within the range of a long. 
*/ 

無論如何,你可以使用Decimal

import decimal 
... 
def getP(dE, t): 
    return decimal.Decimal((-1*dE)/t).exp() 
+0

如前所述,我不能使用try和catch因爲它會返回一個意想不到的數字,這會導致問題(在本例中爲-1),但可以我整數,所以數字不會超過數字限制? –

+0

@YogiWisesa我更新了我的答案;)您可以在這種情況下使用小數 – RaminNietzsche