2011-07-12 11 views
7

Yo escribo una aplicación compatible con punto flotante (casi) IEEE 854 en TeX (que sólo tiene soporte para enteros de 32 bits). Este estándar solo especifica el resultado de +, -, *, /, comparación, resto y sqrt: para esas operaciones, el resultado debe ser idéntico al redondeo del resultado exacto a un número representable (de acuerdo con el modo de redondeo).estándar para el seno de un gran número

Me parece recordar que IEEE especifica que las funciones trascendentales (sin, exp ...) deben dar resultados fieles (por defecto en el asalto a modo cercano, que debe ser la salida a uno de los dos números representables que rodean el resultado exacto) Calcular el seno de números pequeños es bastante sencillo: cambiar por un múltiplo de 2 * pi para obtener un número en el rango [0,2 * pi], luego hacer un poco más de trabajo para reducir el rango a [0, pi/4] y usa una serie de Taylor.

Supongamos ahora que quiero para calcular el pecado (1e300). Para eso necesitaría encontrar 1e300 módulo 2 * pi. Eso requiere saber 300 (316?) Decimales de pi, porque con solo 16 decimales, el resultado no tendría ningún significado en absoluto (en particular, no sería fiel).

¿Existe una norma en lo que debe ser el resultado de sin(1e300) y muy grandes números similares?

¿Qué hacen otras implementaciones de punto flotante?

+1

+1 Agradable explicación de un problema interesante (no había pensado antes) – pavium

Respuesta

8

no existe una norma que requiere fieles redondeo de las funciones trascendentes. IEEE-754 (2008) recomienda, pero no requiere que estas funciones se redondeen correctamente.

La mayoría de las buenas librerías matemáticas se esfuerzan por ofrecer resultados fielmente redondeados en todo el rango (sí, incluso para grandes entradas en sin() y casos similares). Como nota, esto requiere que la biblioteca sepa un poco más dígitos de π luego hay dígitos en el número representable más grande. Esto se llama reducción de argumento "infinito-pi".

Para el punto de que @spraff plantea, buenas bibliotecas matemáticas adoptar el punto de vista de que las entradas son infinitamente preciso (es decir, la función debe comportarse como si la entrada se representa siempre con precisión). Uno puede debatir si esta es una posición razonable o no, pero esa es la suposición de trabajo para esencialmente todas las buenas bibliotecas de matemáticas.

Dicho todo esto, hay muchas bibliotecas que toman la ruta fácil y usan una reducción "finita-pi", que básicamente trata una función como sin() como si π fuera un número finito representable. Resulta que esto realmente no causa ningún problema para la mayoría de los usos , y es ciertamente más fácil de implementar.

+0

"reducción de argumento infinite pi" ayuda cuando tiene argumentos grandes pero no cuando tiene argumentos * muy * grandes. Está bien que una biblioteca asuma que sus entradas son precisas, pero cuando input + epsilon == input ya no importa. – spraff

+1

@spraff: no importa * a los efectos del análisis de error hacia atrás *. Importa cuando se usan otras formas de análisis de errores, y ese es el estándar con el que se sostienen las mejores bibliotecas matemáticas. Ver, por ejemplo, K.C. Ng es "Bueno hasta el último bit" para la discusión. –

+0

En su tercer párrafo, puede observar que las buenas bibliotecas hacen esto porque IEEE-754 (2008) considera que los números de coma flotante son infinitamente precisos. ¿Podría dar ejemplos de "buenas bibliotecas de matemáticas" frente a "las que toman la ruta fácil"? Creo que se agregaría a tu respuesta. Una razón por la cual la ruta fácil no causa muchos problemas es que no viola las identidades trigonométricas como sin (2x) = 2 * sin (x) * cos (x). –

0

Si estás haciendo operaciones en tan gran número, por supuesto que va a quedar sin precisión:

#include <iostream> 
#include <math.h> 

int main() { 
    long double i = 1; 
    std :: cout << sin (i) << "\n" << sin (i+0.1) << "\n"; 
    i = pow (10, 300); 
    std :: cout << sin (i) << "\n" << sin (i+0.1); 
} 

Salida:

0,841471

0,891207

-0,817882

-0.81788

Si no puede representar las entradas con precisión, no puede representar las salidas con precisión. Restando pi*pow(10,int(log_10(n/pi)) o lo que se va a empeorar las cosas para "pequeña" n pero cuando n obtiene convenientemente grande, sólo estás añadiendo ruido a ruido y no importa nada más.

+2

O para ponerlo más simple, '1e300 + 2pi' =' 1e300 - 2pi' = '1e300', por lo que el posible valor exacto representado por '1e300' podría tener cualquier valor como su' sin'? –

+1

@Damien_The_Unbeliever Cuando '1e300' se redondea al valor' doble' representable más cercano, ese redondeo se realiza en un intervalo de longitud '1e284' aproximadamente. Entonces cuando redondeamos '1e300' a un' doble' representable, "pasamos" muchísimos períodos '2pi'-length. Entonces, no tiene sentido tomar 'pecado '. Aún así, matemáticamente, después de haber redondeado el argumento a un valor representable, es posible calcular 'sin' de ese argumento exacto. Para hacerlo, requiere mucha precisión de su representación de '2pi'. Como dije en un comentario a la otra respuesta, en .NET, 'Sin (1e300) == 1e300'. –

Cuestiones relacionadas