根據您的具體需求,將輸入參數裁剪爲exp()
可能會很有用。如果你真的想要得到一個inf
如果它溢出或你想得到荒謬的巨大數字,那麼其他答案會更合適。
def powellBadlyScaled(X):
f1 = 10**4 * X[0] * X[1] - 1
f2 = numpy.exp(-numpy.float(X[0])) + numpy.exp(-numpy.float(X[1])) - 1.0001
return f1 + f2
def powellBadlyScaled2(X):
f1 = 10**4 * X[0] * X[1] - 1
arg1 = -numpy.float(X[0])
arg2 = -numpy.float(X[1])
too_big = log(sys.float_info.max/1000.0) # The 1000.0 puts a margin in to avoid overflow later
too_small = log(sys.float_info.min * 1000.0)
arg1 = max([min([arg1, too_big]), too_small])
arg2 = max([min([arg2, too_big]), too_small])
# print(' too_small = {}, too_big = {}'.format(too_small, too_big)) # Uncomment if you're curious
f2 = numpy.exp(arg1) + numpy.exp(arg2) - 1.0001
return f1 + f2
print('\nTest against overflow: ------------')
x = [-1e5, 0]
print('powellBadlyScaled({}) = {}'.format(x, powellBadlyScaled(x)))
print('powellBadlyScaled2({}) = {}'.format(x, powellBadlyScaled2(x)))
print('\nTest against underflow: ------------')
x = [0, 1e20]
print('powellBadlyScaled({}) = {}'.format(x, powellBadlyScaled(x)))
print('powellBadlyScaled2({}) = {}'.format(x, powellBadlyScaled2(x)))
結果:
Test against overflow: ------------
*** overflow encountered in exp
powellBadlyScaled([-100000.0, 0]) = inf
powellBadlyScaled2([-100000.0, 0]) = 1.79769313486e+305
Test against underflow: ------------
*** underflow encountered in exp
powellBadlyScaled([0, 1e+20]) = -1.0001
powellBadlyScaled2([0, 1e+20]) = -1.0001
注意powellBadlyScaled2
沒有溢出/下溢當原始powellBadlyScaled
做,但修改後的版本給1.79769313486e+305
而不是inf
在測試中的一個。我想有很多應用程序,其中1.79769313486e+305
幾乎是inf
,這將是罰款,甚至是首選,因爲1.79769313486e+305
是一個實數,而inf
不是。
您需要修改算法。如果價值不適合,它不適合。找到一種不同的方式來表達不會溢出的計算。 – 2012-03-04 22:22:25
你可以做的唯一明智的事情是看你的函數的漸近行爲。如果這是明智的,那麼高於某個閾值,則可以用漸近值替換顯式計算。如果漸近值不明智,那麼問題很可能出現在您選擇的算法中,而不是代碼中。 – DaveP 2012-03-04 23:38:18
DaveP,exp的漸近行爲是exp ... – 2012-03-05 12:29:30