首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >OverflowError:数学范围错误-指数Python

OverflowError:数学范围错误-指数Python
EN

Stack Overflow用户
提问于 2017-09-17 04:44:28
回答 1查看 2.4K关注 0票数 0

我试图使用python创建一个简单的模拟退火搜索,但是在使用math.exp计算指数时总是会出现溢出错误。

这是我在python中的代码:

代码语言:javascript
运行
复制
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

错误信息:

代码语言:javascript
运行
复制
 Traceback (most recent call last): 
    return math.exp((-1*dE)/t)
OverflowError: math range error

我尝试使用try和catch,但是它不会返回指数,它会对结果产生问题,我也在谷歌搜索,但没有找到任何符合我的要求的解决方案。

之前谢谢你!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-17 04:59:34

异常OverflowError

当算术运算的结果太大而无法表示时引发。对于长整数(它宁愿提高MemoryError而不是放弃)和大多数使用普通整数返回长整数的操作,都不会发生这种情况。由于C语言中浮点异常处理缺乏标准化,大多数浮点操作也没有被检查。参考

你试着计算一个大的数字(大于710),这超出了双倍的范围。

您可以像这样使用try/except来处理它:

代码语言:javascript
运行
复制
def getP(dE, t):
    try:
        return math.exp((-1*dE)/t)
    except:
        return -1 # or anything else :D

您可以在Python的代码中找到这个注释:

代码语言:javascript
运行
复制
/*
 * 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

代码语言:javascript
运行
复制
import decimal
...
def getP(dE, t):
    return decimal.Decimal((-1*dE)/t).exp()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46260731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档