zależności od konkretnych potrzeb , może być użyteczne przycięcie argumentu wejściowego do exp()
. Jeśli rzeczywiście chcesz uzyskać inf
, jeśli przepełniasz lub chcesz uzyskać absurdalnie duże liczby, wtedy inne odpowiedzi będą bardziej odpowiednie.
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)))
Wynik:
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
Uwaga, powellBadlyScaled2
nie powyżej/niedomiar gdy oryginalny powellBadlyScaled
zrobił, ale zmodyfikowana wersja daje 1.79769313486e+305
zamiast inf
w jednym z testów. Wyobrażam sobie, że istnieje wiele aplikacji, w których 1.79769313486e+305
jest praktycznie inf
i byłoby to w porządku, a nawet preferowane, ponieważ 1.79769313486e+305
jest liczbą rzeczywistą, a inf
nie.
Musisz dostosować swój algorytm. Jeśli wartość nie pasuje, nie pasuje. Znajdź inny sposób wyrażenia obliczeń, które się nie przelewają. –
Jedyną rozsądną rzeczą, którą możesz zrobić, to spojrzeć na asymptotyczne zachowanie swojej funkcji. Jeśli jest to rozsądne, to powyżej pewnego progu można zastąpić wyraźne obliczenie wartością asymptotyczną. Jeśli wartość asymptotyczna nie jest sensowna, problem jest najprawdopodobniej związany z wyborem algorytmu, a nie z kodem. – DaveP
DaveP, asymptotyczne zachowanie exp jest exp ... –