Comunidad de diseño web y desarrollo en internet

Aproximar funciones trigonométricas seno y coseno en Flash

Extendiendo un poco el tema de aproximar funciones matemáticas complejas que comencé en éste post. Agrego ahora un modo de aproximar las funciones seno y coseno que encontré en Internet.

Antes de empezar, quiero aclarar que la información la tomé de éste post de la página Polygonal Labs, que a su vez encontró la información en éste post.

Luego de aclarado eso, vamos a lo verdaderamente interesante.

Quizá lo primero que se nos ocurre para aproximar una función cualquiera (trigonométricas incluidas) es usar una serie de Taylor (recuerdo haberlo intentado).

El problema es que la fórmula es algo complicada y sólo aproxima correctamente cerca del origen (ya que centramos Taylor en 0, por practicidad)



En el ejemplo, se puede ver el seno en verde y el polinomio de Taylor de grado 4 en rojo.

Si hacemos un Zoom, vemos como se comporta fantásticamente hasta π/2 para luego desviarse.



Por supuesto, podríamos tomar Taylor de un mayor órden, pero la idea es hacer las cuentas lo más cortas posibles.

Entonces, es cuando la genialidad surge. Por si no lo habían notado, la función seno en un período se parece a una parábola. Donde:

a = 0
b = 4/π
c = -4/π^2




Pero no es una gran aproximación, incluso, es obvio que es aún peor que usar Taylor.

En éste punto vale aclarar que cuando necesitamos valores negativos, podemos invertir la parábola



Bien, continuando con lo anterior, vamos a buscar una solución al problema de la falta de calidad. Para solucionarlo, observamos que el error es siempre por exceso (es decir, que los valores son mayores o iguales a los verdaderos). Entonces, buscamos una función cuyo error sea por defecto (es decir, valores menores), teniendo cuidado en que sea correcto el valor en 0, π/2 y π



Podemos observar que el módulo del error es mayor al de la aproximación anterior.

Bueno, promediamos ambos valores y obtenemos una aproximación aún mejor. Es más, la aproximación es casi perfecta.



Sólo falta aclarar que las ecuaciones para el coseno son bastante parecidas (apenas un poco más complejas) a las del seno.

Pero basta de teoría. El código sería el siguiente (para la primer aproximación, 14 veces más rápida):

Código :

// Mantenemos el ángulo entre -π  y π
if (x < -3.14159265) {
    x += 6.28318531;
} else if (x >  3.14159265) {
    x -= 6.28318531;
}
// Obtenemos el seno
if (x < 0) {
    sin = 1.27323954 * x + .405284735 * x * x;
} else {
    sin = 1.27323954 * x - 0.405284735 * x * x;
}
// Obtenemos el coseno
x += 1.57079632;
if (x >  3.14159265) {
    x -= 6.28318531;
}
if (x < 0) {
    cos = 1.27323954 * x + 0.405284735 * x * x
} else {
    cos = 1.27323954 * x - 0.405284735 * x * x;
}
}


Para la segunda aproximación (más precisa, pero 8 veces más rápida):

Código :

// Mantenemos el ángulo entre -π  y π
if (x < -3.14159265) {
    x += 6.28318531;
} else if (x >  3.14159265) {
    x -= 6.28318531;
}
// Obtenemos el seno
if (x < 0) {
    sin = 1.27323954 * x + .405284735 * x * x;
    if (sin < 0) {
        sin = .225 * (sin *-sin - sin) + sin;
    } else {
        sin = .225 * (sin * sin - sin) + sin;
    }
} else {
    sin = 1.27323954 * x - 0.405284735 * x * x;
    if (sin < 0) {
        sin = .225 * (sin *-sin - sin) + sin;
    } else {
        sin = .225 * (sin * sin - sin) + sin;
    }
}
// Obtenemos el coseno
x += 1.57079632;
if (x >  3.14159265) {
        x -= 6.28318531;
    }
if (x < 0) {
    cos = 1.27323954 * x + 0.405284735 * x * x
    if (cos < 0) {
        cos = .225 * (cos *-cos - cos) + cos;
    } else {
        cos = .225 * (cos * cos - cos) + cos;
    }
} else {
    cos = 1.27323954 * x - 0.405284735 * x * x;
    if (cos < 0)
        cos = .225 * (cos *-cos - cos) + cos;
    else
        cos = .225 * (cos * cos - cos) + cos;
}


Aclaro que no ubicamos el código en una función ya que consume importantes recursos.

Eso es todo, espero les sirva.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate