A seconda delle esigenze specifiche , potrebbe essere utile ritagliare l'argomento di input su exp()
. Se in realtà vuoi ottenere uno fuori se esso trabocca o vuoi ottenere numeri enormi assurdamente, allora altre risposte saranno più appropriate.
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)))
Risultato:
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
noti che powellBadlyScaled2
invece no over/underflow quando l'originale powellBadlyScaled
ha fatto, ma la versione modificata dà 1.79769313486e+305
invece di inf
in uno dei test. Immagino ci siano un sacco di applicazioni in cui 1.79769313486e+305
è praticamente inf
e questo andrebbe bene, o addirittura preferito perché 1.79769313486e+305
è un numero reale e non lo è inf
.
fonte
2018-01-12 05:24:40
Avrai bisogno di adattare il tuo algoritmo. Se il valore non si adatta, non si adatta. Trova un modo diverso per esprimere il calcolo che non trabocca. –
L'unica cosa sensata che puoi fare è osservare il comportamento asintotico della tua funzione. Se ciò è sensato, allora al di sopra di qualche soglia puoi sostituire il calcolo esplicito con il valore asintotico. Se il valore asintotico non è sensibile, il problema è molto probabilmente nella scelta dell'algoritmo, non nel codice. – DaveP
DaveP, il comportamento asintotico di exp è exp ... –