2017-09-17 100 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 

私がしようとするとキャッチを使用しようとしているが、それは、指数の数を返しません、それはAになります結果に問題があり、私もグーグルで試していますが、私の要求を満たす解決策は見つかりません。

ありがとうございました!

+0

できましたエラートレースバックを投稿する –

+0

( - 1 * dE)/ t、これらは非常に大きくても非常に小さいかもしれませんが、これまでに述べたように –

答えて

0

exception OverflowError

算術演算の結果が大きすぎて表現できない場合に発生します。これは長い整数(あまりにもMemoryErrorを上げるよりもむしろ)と、長い整数を代わりに返す単純な整数を伴うほとんどの操作では発生しません。 C言語で浮動小数点例外処理の標準化が行われていないため、ほとんどの浮動小数点演算もチェックされません。 Ref

大きな数値(710より大きい)を計算しようとしましたが、これは倍数の範囲外です。あなたはこのような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

は試行錯誤して使用できません。数字が数字の制限を超えないように数字を丸めますか? –

+0

@ YogiWisesa私の答えを更新;)この状況では10進数を使用できます – RaminNietzsche