¿Existe una función seno más rápida?

25

Estoy trabajando en la generación de ruido 3d perlin. La biblioteca de C # Math parece exagerada para lo que necesito, ya que la mayoría de sus funciones utilizan doble precisión. Yo uso Math.Sin () en varios lugares para generar el ruido. ¿Alguien sabe de una función seno más rápida?

usuario2709
fuente

Respuestas:

32

Puede usar una parábola para aproximar el valor de la función seno. Esto tiene la ventaja de tener las raíces exactamente en -pi / 2 y pi / 2, que generalmente no es el caso con otras aproximaciones rápidas basadas en TaylorSeries o MaclaurinSeries .

public float Sin(float x)
{
    const float B = 4 / PI;
    const float C = -4 / (PI*PI);

    return -(B * x + C * x * ((x < 0) ? -x : x));
} 

Aquí hay una comparación con la función seno real:

texto alternativo

zfedoran
fuente
3
De hecho, esta es una gran solución. Aquí hay un excelente artículo de devmaster.net que describe por qué esto funciona y brinda algunos detalles de implementación: devmaster.net/forums/showthread.php?t=5784
reverbb
No sé acerca de C #, pero la función abs () en la mayoría de los entornos de C probablemente será más rápida que una rama (el operador?:), Cuando se optimiza.
3
Eliminé la llamada Math.Abs ​​() porque supuse que este código podría ejecutarse en Xbox 360 o Windows Phone 7. El compilador JIT en Xbox 360 no incluye nada en línea. Una llamada a Math.Abs ​​() es en realidad más costosa.
zfedoran
@reverbb Link es 404. Aquí hay una copia en caché.
Daniel Pendergast
1
@zfedoran ¿Por qué niega el valor de retorno? Parece ser una onda sinusoidal negativa.
Daniel Pendergast
12

¿Cuál es el rango de valores de entrada para su función sin () ? Para lo que lo está utilizando, parece que podrían ser limitados, lo que significa que podría calcular previamente los valores . Por ejemplo, si está redondeando los valores de entrada al grado más cercano, entonces solo tiene 360 ​​valores posibles, solo calcule previamente y almacénelos en una tabla.

Si necesita un poco más de valores, digamos con un decimal, puede interpolar desde la tabla; no estoy familiarizado con el ruido perlin , pero la palabra "ruido" parece indicar que no requiere una alta precisión. :) (También podría hacer una tabla más grande, 3600 entradas no es mucho espacio).

Cíclope
fuente
3
Si la velocidad es su principal preocupación, y no le importa sacrificar un poco de precisión, esta es la mejor respuesta.
AttackingHobo
1
No sé sobre "mejor": como se muestra en otra respuesta, puede obtener otra muy buena aproximación en cinco operaciones + abdominales (la velocidad de la cual depende de su arch / compilador, pero a menudo no tiene ramificaciones). Si la tabla de búsqueda no está en caché, será mucho más lenta.