[Python-es] El infinito se me queda corto

Hernán Foffani hfoffani en gmail.com
Lun Mar 25 18:07:35 CET 2013


>>>>>> Supongo que habrá una explicación. Si realizo el siguiente cálculo:
>>>>>> 
>>>>>> In [13]: import math
>>>>>> 
>>>>>> In [14]: math.tan(math.pi/2)
>>>>>> Out[14]: 1.633123935319537e+16
>>>>>> 
>>>>>> Aunque no esperaba que me diese la solución correcta de
>>>>>> float("+inf")/float("-inf"), me resulta muy corto para el tamaño
>>>>>> máximo que podría tener un double:
>>>>>> 
>>>>>> In [16]: sys.float_info.max
>>>>>> Out[16]: 1.7976931348623157e+308
>>>>>> 
>>>>>> He comprobado que pasa lo mismo con scala e, incluso, en el
>>>>>> buscador de google (tal vez sea que google usa también python):
>>>>>> 
>>>>>> https://www.google.com/search?q=tan(pi%2F2)
>>>>>> 
>>>>>> ¿Existe alguna explicación?
>> 
>> 
>> Supongo que a esta altura ya lo has resuelto, pero si no, añado algunas precisiones (pun intended).
>> 
>> Lo de Python/Scala/Google es por la libm, la biblioteca matemática estándar de C. Esto muestra el mismo resultado que ves en Python (M_PI_2 es la constante PI/2 ya definida en la biblioteca):
>> 
>>        #include <math.h>
>>        #include <stdio.h>
>>        int main() { printf("%f\n", tan(M_PI_2)); }
>> 
>> Matemáticamente hablando tan(pi/2) no está definido. El límite para valores tendiendo a pi/2 desde 0 es +inf y -inf para x desde 3.
>> Lo que mejor podría hacer tan() es devolver NaN pero debería saber que x es exactamente PI y no un número menor/mayor. Si pruebas con valores ligeramente mayores a M_PI_2 verás que tan() sí cambia el signo.
>> 
>> La biblioteca resuelve bien algunas operaciones desde el punto de vista matemático ( ej. 1/+inf ) y otras no (ej. pow(-1, +inf) -> 1 y debería ser NaN o domain error). Las libm están llenas de compromisos de ese estilo por performance, implementación, precisión, etc. A esta altura su comportamiento está completamente estandarizado.
>> 
> 
> Me había quedado claro que es un tema de la librería matemática. Mi
> extrañeza venía por el bajo orden de magnitud del resultado, que queda
> explicado por la falta de precisión del número pi que emplea la
> librería matemática.
> 
> Tal vez se aprecie mejor desde el lado contrario:
> 
> In [1]: import sys, math
> In [2]: casi_infinito=sys.float_info.max
> In [3]: casi_infinito
> Out[3]: 1.7976931348623157e+308
> In [4]: math.atan(casi_infinito)*2==math.pi
> Out[4]: True
> In [5]: math.atan(1.7e+16)*2==math.pi
> Out[5]: True


Así es. El "siguiente" valor a PI/2 que se podría representar en flotantes es PI/2 + epsilon, pero ese ya se pasa y la tangente ya viene del -inf.
	>>> import sys
	>>> import math
	>>>
	>>> math.tan((math.pi/2)+sys.float_info.epsilon)
	-6218431163823738.0
	>>>

-H.
 





Más información sobre la lista de distribución Python-es