Buscando un algoritmo arcsin


7

¿Alguien tiene un algoritmo simple para calcular un arcoseno razonablemente preciso? Por "simple" me refiero a algún tipo de polinomio que requiere <= 5 multiplicados por muestra de salida. Y por "razonablemente preciso" me refiero a un error cuyo error no es más del 10% cuando el argumento de entrada está cerca de más o menos uno. Busqué en la web por un tiempo pero no encontré nada inmediatamente útil.


Esto podría dar algunas ideas stackoverflow.com/questions/5920467/…
geometrikal

Pero, ¿por qué no solo una tabla de búsqueda?
geometrikal

Estoy pensando en una implementación donde la memoria disponible es dolorosamente limitada. Así que no consideré ninguna solución de "tabla de consulta". Gracias por tus pensamientos
Richard Lyons el

¿Permiten raíces cuadradas? Debido al comportamiento de la función cerca de±1(pendiente infinita), una aproximación polinómica no funciona bien allí.
Yves Daoust

¿Qué pasa con CORDIC?
Mattgately

Respuestas:


5

Aquí hay solo una versión polinómica :

arcsin(x)=x+12x33+1324x55+135246x77
function y = arcsin_test3(x)
    y = x.*(1+x.*x.*(1/6+ x.*x.*(3/(2*4*5) + x.*x.*((1*3*5)/(2*4*6*7)))))
endfunction

que parece tener cinco multiplicaciones (suponiendo que pueda guardar el resultado x.*x) y tres adiciones.

Y la scilabtrama es:

ingrese la descripción de la imagen aquí

La parte superior es scilab's asincontra esta, la parte inferior es el error entre los dos.


Respuesta original

La raíz cuadrada aquí puede ser una molestia, pero pensé en escribirla porque parece divertida. :-)

Esta página sugiere:

de la página 81 del Manual de funciones matemáticas, por Milton Abramowitz e Irene Stegun:

arcsin(x)=π/21x(a0+a1x+a2x2+a3x3),
dónde
a0=1.5707288a1=0.2121144a2=0.0742610a3=0.0187293

He implementado esto scilaby funciona bien, excepto alrededorx=1. Solo reflejando el0x1 a 1x0 hace una aproximación mucho mejor.

La gráfica superior muestra scilabla asinfunción de la aproximación anterior (en rojo discontinuo) contra mi cambio en verde.

La gráfica inferior muestra el error para mi cambio (trazar eso y el original en los mismos ejes significa que el verde parece cero en todas partes).

ingrese la descripción de la imagen aquí

// 25770
function y = arcsin_test(x)
    a0 = 1.5707288
    a1 = -0.2121144
    a2 = 0.0742610
    a3 = -0.0187293

    xx = abs(x)

    y = %pi/2 - sqrt(1-x).*(a0 + a1*x + a2.*x.*x + a3.*x.*x.*x)

endfunction

function y = arcsin_test2(x)
    a0 = 1.5707288
    a1 = -0.2121144
    a2 = 0.0742610
    a3 = -0.0187293

    xx = abs(x)

    y = %pi/2 - sqrt(1-xx).*(a0 + a1*xx + a2.*xx.*xx + a3.*xx.*xx.*xx)

    y = y.*sign(x); 
endfunction

x = [-1: .0100001 : 1];

clf
subplot(211)
plot(x,arcsin_test2(x),'g.');
plot(x,arcsin_test(x),'r:');
plot(x,asin(x))
subplot(212)
//plot(x,(arcsin_test(x) - asin(x)),'r:')
plot(x,(arcsin_test2(x) - asin(x)),'g.')

2
"Handbook of Mathematical Functions" ama ese libro
geometrikal

1
Oh dispara. ¡Vi esa página web wiki 'funciones trigonométricas inversas' durante mi búsqueda en la web pero no me desplacé lo suficiente como para ver el material de 'series infinitas'! Me avergüenza. Peter K., ese es otro que te debo. (Mi problema original era mejorar el rendimiento de un diferenciador digital de diferencia central que, creo, se puede hacer realizando una operación de arco).
Richard Lyons,

Sí, pero Rick, no puedes hacer una serie infinita. si vas a hacerlo finito, entonces los coeficientes óptimos no serán exactamente lo que obtienes al truncar las series infinitas. si tiene MATLAB funcionando (ahora tienen una licencia de "uso doméstico" relativamente barata), puedo enviarle el código MATLAB para realizar el intercambio de Remez en función del deseo de su corazón.
robert bristow-johnson

1
ACTUALIZACIÓN: pude resolver mi problema original (creando un diferenciador digital muy simple que ha mejorado el rendimiento sobre el de un diferenciador de diferencia central) sin usar una función arcsin (). Puedo publicar un blog en dsprelated.com describiendo mis resultados. ¡Agradezco a todos los presentes por su ayuda!
Richard Lyons

3

tengo una muy buena implementación de arctan() Aquí .

Creo que puedes usar la identidad:

arcsin(x)=arctan(x1x2)

para conseguir lo que quieres


Su enlace a varias funciones es interesante Robert. Solo por risas intenté implementar la función sqrt (1 + x). En lugar de usar los límites correctos de 0 a 4, me equivoqué y usé 1 a 5. Por supuesto, calculé un resultado incorrecto. Sin embargo, cuando multipliqué mi resultado "incorrecto" por dos, terminé con el resultado correcto. Interesante, ¿eh?
Richard Lyons

Rick, estoy bastante seguro de que las funciones son "correctas" (o razonablemente precisas) como están con los límites de xcomo se indica parax, solo es bueno para 1x2, así que si estás entre 2 y 4, entonces tendrás que tener un poco constante (el 2) almacenado allí y necesitará saber la diferencia entre un exponente par de 2 y un extraño exponente de 2.
robert bristow-johnson

Yo también creo que tus funciones son correctas. Simplemente estaba comentando un error tonto de 'límites de suma' que cometí, y al cometer mi error calculé un resultado incorrecto. Pero noté que mi resultado incorrecto era exactamente la mitad del resultado correcto. Solo decía que mi resultado incorrecto tenía una relación "interesante" con el resultado correcto, eso es todo. Perdón por la confusión, Robert.
Richard Lyons

2

La parte central de la curva no es un problema real, ya que es bastante lineal y la aproximación de Taylor a dos o tres términos es un buen punto de partida (el polinomio de mínimos cuadrados se ajusta un poco mejor).

Los lados son más problemáticos debido a la pendiente infinita. Una forma de hacer frente es a través de la transformación

arcsin(x)=π2arcsin(1x2),

que implica una raíz cuadrada.


Si tu argumento z se representa con coma flotante, se obtiene una aproximación rápida de la raíz cuadrada reduciendo a la mitad el exponente y aplicando una transformación lineal a la mantisa.

Dejar z=m2e, con 1m<2, entonces z=m2e/2. Puedes aproximarm por (21)(m+2).

  • toma el exponente e aparte (limpiarlo produce la representación de m);
  • Si e es par, calcular (21)(m+2);
  • Si e es extraño, calcular 2(21)(m+2);
  • establecer el exponente e/2.

ingrese la descripción de la imagen aquí


¡Espero experimentar con ese interesante algoritmo de raíz cuadrada!
Richard Lyons

Con estos coeficientes, el error siempre es positivo. Mediante un ligero ajuste, podemos hacerlo simétrico y reducir a la mitad el error máximo.
Yves Daoust
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.