¿Cómo calcular la función Sin de forma más rápida y precisa?

8

Quiero calcular y(n)=32677Sin(45/1024•n), dónde yes un número entero y nvaría de 0 a 2048. ¿Cómo puedo hacer este proceso más rápido y con mayor precisión? Ahora quiero mostrarle una respuesta de referencia: desde Sin(a+b)=Sin(a)Cos(b)+Cos(a)Sin(b) And Cos(a+b)=Cos(a)Cos(b)-Sin(a)Cos(b). Entonces puedo almacenar Sin(45/1024•1)y solo. Cos(45/1024•1)Luego use esta fórmula:

Sin(45/1024•2)=Sin(45/1024•1+45/1024•1), Cos(45/1024•2)=Cos(45/1024•1+45/1024•1), Sin(45/1024•n)=Sin(45/1024•(n-1)+45/1024•1), Cos(45/1024•n)=Cos(45/1024•(n-1)+45/1024•1), De esta manera tal vez más rápido sin almacenar gran variedad.

LaiJong
fuente
Esta pregunta es apropiada para los Programadores, suponiendo que la intención es aprender sobre los algoritmos y / o estructuras de datos apropiados desde la perspectiva de las preocupaciones de ingeniería de software.
Thomas Owens
8
Ese 45 es un poco sospechoso; me hace pensar que quieres sin(x)dónde xestá en grados. Si ese es el caso, debe tener en cuenta que el argumento de las funciones trigonométricas generalmente está en radianes. El argumento está en radianes en C ++, que es cómo se etiqueta esta pregunta.
David Hammen
¿Por qué necesitas responder esta pregunta? ¿Cuál es la aplicación?
GlenPeterson
¿Qué tan preciso necesita que sea el resultado?
dan04
@ dan04 Dado que y es un número entero, lo necesito con precisión como número entero.
LaiJong

Respuestas:

18

Si el nrango va de 0 a 2048, puede calcular previamente los valores, almacenarlos en una matriz. y(n)se convertiría values[n].

vartec
fuente
+1 y puede interpolar cualquier valor intermedio (si es posible).
Daniel B
1
Esa es una opción viable, aunque todavía la perfilaría para asegurarme de que sea más eficiente que calcularla (por ejemplo, las FPU fsinpodrían usarse y ser más amigables con la caché que algunas matrices).
Benjamin Bannier
¿Qué tal no almacenar el valor [n]?
LaiJong
3
Las funciones trigonométricas son muy lentas de calcular sobre la marcha. Estoy bastante seguro de que cada implementación rápida utiliza valores precalculados. Como sin () y cos () son periódicos, solo necesita almacenar los primeros 90 grados. Puede devolver -sin (), o sin (90 - el ángulo), o -sin (90 - el ángulo) dependiendo del cuadrante. También puede definir cos () en términos de sin (). Si conoce el posible rango de valores de entrada, puede calcular previamente y solo almacenar los valores que necesita para su programa. De lo contrario, la interpolación entre un número limitado de valores puede ser su opción más rápida.
GlenPeterson
1
@Glen: los valores de Sin están entre -1 y 1, por lo que en realidad cabe en 16 bits sin signo.
vartec
1

Calcule la tabla en tiempo de compilación en lugar de tiempo de ejecución.

Estás haciendo una tabla de 2048 elementos de valores enteros escalados de 16 bits.

Escriba un script Matlab barato, con una impresión que proporcione una línea de datos adecuada para su lenguaje de programación final. Corte y pegue el resultado en su código fuente, como una tabla de datos constante, y realice una búsqueda de tabla en tiempo de ejecución. Esto empuja el tiempo de cálculo inicial al ciclo de compilación, en lugar del tiempo de inicio del programa.

John R. Strohm
fuente
¿Cuánto tiempo de ejecución ahorra en comparación con el costo adicional del programador?
JBRWilkinson
Rápido y sucio. Agradable.
cuant
1

Dada la forma de la función, la respuesta natural es el algoritmo CORDIC . Es un enfoque mucho más limpio que el desglose de la pregunta. Por otro lado, la tabla que necesita es mucho, mucho más pequeña que la tabla que otros han sugerido.

MSalters
fuente