Dependiendo de sus necesidades específicas , puede ser útil recortar el argumento de entrada al exp()
. Si realmente desea obtener un inf
si se desborda o si desea obtener números absurdamente enormes, entonces otras respuestas serán más apropiadas.
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)))
Resultado:
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
en cuenta que no lo hicieron powellBadlyScaled2
sobre/desbordamiento cuando el original powellBadlyScaled
lo hicieron, pero la versión modificada da 1.79769313486e+305
inf
en lugar de en una de las pruebas. Me imagino que hay un montón de aplicaciones donde 1.79769313486e+305
es prácticamente inf
y esto estaría bien, o incluso preferido porque 1.79769313486e+305
es un número real y inf
no lo es.
Deberás adaptar tu algoritmo. Si el valor no encaja, no encaja. Encuentre una forma diferente de expresar el cálculo que no se desborde. –
Lo único sensato que puede hacer es observar el comportamiento asintótico de su función. Si eso es razonable, entonces, por encima de un umbral, puede reemplazar el cálculo explícito por el valor asintótico. Si el valor asintótico no es sensible, entonces es más probable que el problema esté en su elección de algoritmo, no en el código. – DaveP
DaveP, comportamiento asintótico de exp es exp ... –