26 votos

¿Por qué las diferentes calculadoras no se ponen de acuerdo sobre $\cos(452175521116192774 )$ ?

Quiero calcular el coseno de 452175521116192774 radianes (está alrededor de $4.52\cdot10^{17}$ )
Esto es lo que dicen diferentes calculadoras:

Wolframalpha WolframAlpha

Desmos

Desmos

Geogebra

Geogebra

Python 3.9 (módulo matemático estándar)

Python

Python 3.9 (biblioteca mpmath)

Python3

Obviamente, sólo hay una solución. Podría haber errores en la precisión en coma flotante de estas calculadoras, pero esto me deja perplejo. Mi calculadora (TI-30XIS) dice error de dominio (lo cual es raro porque el coseno de, por ejemplo, mil millones funciona perfectamente). ¿Cómo puedo obtener el coseno de números enteros muy grandes?

56voto

Lars Truijens Puntos 24005

El problema es que su entero $$n=452175521116192774$$ no puede almacenarse exactamente como un estándar de 64 bits IEEE doble precisión número en coma flotante. El doble más cercano resulta ser $$x=452175521116192768,$$ como puede verse en la representación binaria $$ \begin{aligned} n &= 11001000110011100110011110110100000010000100000000000\color{red}{000110}_2 \\ x &= 11001000110011100110011110110100000010000100000000000\color{red}{000000}_2 \end{aligned} $$ donde esos últimos bits en $n$ se pierden, ya que el formato doble sólo almacena los 52 primeros dígitos después del "1" inicial.

Así que en los sistemas que utilizan coma flotante estándar (como Desmos, Geogebra, y el módulo matemático de Python) en realidad obtendrá $x$ al entrar $n$ en un lugar donde se espera un double; en Python puedes comprobarlo de la siguiente manera:

> print("%.310g" % 452175521116192774)
452175521116192768

En consecuencia, cuando pida $\cos n$ estos sistemas responderán con $$\cos x = -0.2639 \ldots$$ (que en sí mismo se computa correctamente; es sólo que la entrada no es lo que pensabas).

En cambio, Wolfram Alpha y mpmath trabajan con el número exacto $n$ y dar la respuesta correcta $$\cos n = -0.5229 \ldots$$

4voto

Stephen Denne Puntos 218

Como señaló Hans Lundmark el problema se debe a la conversión del argumento a un C double antes de realizar el cálculo.

Pero si no quieres recurrir a una biblioteca matemática de alta precisión, hay una forma (al menos en Python) de calcular un valor más exacto utilizando las identidades de suma de ángulos.

from math import cos, sin

def cossin(x):
    '''
    Return (cos(x), sin(x)) more accurately.
    '''
    if abs(x) < 2 ** 53:
        # All integers below this threshold are represented exactly,
        # so just use the normal math module functions.
        return (cos(x), sin(x))
    else:
        a = float(x)
        b = x - int(a)  # the approximation error
        # a is a float, so use the normal math functions.
        cos_a = cos(a)
        sin_a = sin(a)
        # for b, call recursively in case *it* can't be represented as float
        cos_b, sin_b = cossin(b)
        return (cos_a * cos_b - sin_a * sin_b, cos_a * sin_b + sin_a * cos_b)

Esto coincide bastante con el resultado de WolframAlpha.

>>> cossin(452175521116192774)
(-0.5229034783961185, -0.8523919006426797)

Un enfoque alternativo es utilizar una aproximación de alta precisión de para reducir el argumento módulo 2. (En Python, puede utilizar la clase Fraction para almacenar su aproximación. Esto te da:

$$452175521116192774 \approx 71965969330795778 \times 2\pi + 4.162135302888925$$

Y tomar el coseno del argumento reducido te dará el resultado correcto.

>>> cos(4.162135302888925)
-0.5229034783961188

-2voto

Su calculadora Texas Instruments es probablemente un modelo inferior creado por ingenieros que hicieron lo que pudieron mientras estaban sometidos a severas limitaciones de tiempo y presupuesto, supervisados por brutales directivos capitalistas a los que sólo les importa cumplir ciertos hitos en un diagrama de Gantt.

Mi WP-34S (en modo de doble precisión) es capaz de representar tu número con un dígito de sobra. Tentando a la suerte, la función coseno en modo radián arroja -0,52290347840 en la pantalla. Por desgracia, esta calculadora era demasiado buena, así que HP dejó de fabricar la plataforma HP 30b Business Professional en la que se basaba. Pero puedes descargar un emulador gratuito para tu iPhone. Ese emulador ejecuta programas largos MUCHO más rápido que el hardware original de la calculadora.

¿Cómo computaría USTED semejante monstruo? ¿Restar un múltiplo apropiado de 2 pi para poner el argumento en un rango que la calculadora pueda manejar? Lo siento, no tienes suficientes dígitos para hacerlo.

Creo que lo mejor que puedes hacer es dividir el argumento por alguna potencia grande de 2 y, a continuación, utilizar repetidamente las fórmulas de ángulo doble para obtener la función trigonométrica del ángulo deseado. Desgraciadamente, la mayor potencia de 2 que divide tu argumento es 4. Después de eso, una nueva división por dos añade más dígitos de los que puede contener tu máquina. Necesitas coma flotante de precisión cuádruple para representar tu argumento en un ordenador, y mucho más que eso para representar el argumento dividido por una gran potencia de dos. Y si ni siquiera puedes representarlo, no puedes calcular el coseno.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X