El día 20 de marzo de 2013 13:19, José Sabater Montes <[email protected]> escribió: > > 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.
Por lo que parece, la tendencia a infinito está en relación con la precisión del cálculo. Cuanto más digitos de precisión, tanto más grande será el número Comprobando con mpmath: dps resultado aprox. ------ | ----------------------- 10 390115388672.0 15 1.63312393531954e+16 50 -1.97883490126957e+51 100 6.97133053829442e+101 300 1.59802604184178e+301 1000 2.84594257232622e+1001 5000 -1.04829403956079e+5001 10000 -7.59194855601038e+10001 12000 8.19055339712727e+12001 15000 1.18530955294349e+15001 20000 1.34274677646898e+20001 30000 -1.14011942791359e+30001 El que alternen los signos supongo que será cosa del algorítmo de aproximación. -- Hyperreals *R: http://ch3m4.org/blog Quarks, bits y otras criaturas infinitesimales _______________________________________________ Python-es mailing list [email protected] http://mail.python.org/mailman/listinfo/python-es FAQ: http://python-es-faq.wikidot.com/
