Hola,

El 20/03/2013, a las 11:00, Chema Cortes escribió:

> 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?

>>> import math
>>> math.pi/2.
1.5707963267948966

Aparentemente la tangente de ese número con esa precisión es exactamente esa 
calculando con la precisión de un float.
Para aumentar la precisión creo que hay que usar una librería que ofrezca 
precisión arbitraria como el módulo "decimal" de la librería estándar o mpmath.
El problema con "decimal" es que no implementa funciones matemáticas un poco 
más complejas como las trigonométricas, así que el resultado de la tangente 
sería el mismo si se usan las mismas funciones que antes.

>>> from decimal import Decimal
>>> pi_dec = Decimal('3.1415926535897932384626433832795028841971693993751')
>>> pi_dec
Decimal('3.1415926535897932384626433832795028841971693993751')
>>> pi_dec/Decimal('2')
Decimal('1.570796326794896619231321692')
>>> math.tan(pi_dec/Decimal('2'))
1.633123935319537e+16

Si no me equivoco, las funciones trigonométricas se suelen calcular usando 
series. Una buena librería de precisión arbitraria (supongo que todas) irá 
adaptando el número de sumandos a la precisión requerida. Por ejemplo:

>>> from mpmath import *
>>> tan(1.5707963267948966)
mpf('16331239353195370.0')
>>> tan(pi/2)
mpf('16331239353195370.0')

Aumentamos la precisión

>>> mp.dps = 50
>>> tan(1.5707963267948966)
mpf('16331239353195369.755967737041528916530864068104910291')
>>> tan(pi/2)
mpf('-1978834901269570871682051952580899049722178117311132.0')
>>> tan(mpf('1.5707963267948966192313216916397514420985846996875534'))
mpf('-1978834901269570871682051952580899049722178117311132.0')


> ¿Algún modo de ajustar más el resultado a
> infinito (sin ser la solución trivial de comprobar los parámetros de
> entrada)?

Creo que la única opción es usar un módulo matemático de precisión arbitraria 
como mpmath o bigfloat.

Un saludo.

_______________________________________________
Python-es mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/

Responder a