Existe uma função senoidal mais rápida?

25

Estou trabalhando na geração de ruído perlin 3d. A biblioteca C # Math parece um exagero para o que eu preciso, pois a maioria de suas funções usa percisão dupla. Eu uso Math.Sin () em vários lugares para gerar o ruído. Alguém sabe de uma função senoidal mais rápida?

user2709
fonte

Respostas:

32

Você pode usar uma parábola para aproximar o valor da função seno. Isso tem a vantagem de ter as raízes exatamente -pi / 2 e pi / 2, o que geralmente não é o caso de outras aproximações rápidas baseadas no TaylorSeries ou 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));
} 

Aqui está uma comparação com a função seno real:

texto alternativo

zfedoran
fonte
3
Esta é realmente uma ótima solução. Aqui está um excelente artigo de devmaster.net que descreve por que isso funciona e dá alguns detalhes de implementação: devmaster.net/forums/showthread.php?t=5784
reverbb
Não sei sobre C #, mas a função abs () na maioria dos ambientes C provavelmente será mais rápida que uma ramificação (o operador?:), Quando otimizada.
3
Eu removi a chamada Math.Abs ​​() porque presumi que esse código poderia ser executado no Xbox 360 ou Windows Phone 7. O compilador JIT no Xbox 360 não alinha nada. Uma chamada para Math.Abs ​​() é realmente mais cara.
Zfedoran
@reverbb O link é 404. Aqui está uma cópia em cache.
precisa
11
@zfedoran Por que você nega o valor de retorno? Parece ser uma onda senoidal negativa.
precisa saber é o seguinte
12

Qual é o intervalo de valores de entrada para sua função sin () ? Para o que você está usando, parece que eles podem ser limitados, o que significa que você pode pré-calcular os valores . Por exemplo, se você estiver arredondando os valores de entrada para o grau mais próximo, terá apenas 360 valores possíveis - basta pré-calculá-los e armazená-los em uma tabela.

Se você precisar de um pouco mais de valor, digamos com uma casa decimal, poderá interpolar da tabela - não estou familiarizado com o ruído permanente , mas a palavra "ruído" parece indicar que não exige alta precisão. :) (Você também pode criar uma tabela maior, 3600 entradas não são muito espaço).

Cyclops
fonte
3
Se a velocidade é sua preocupação número um e você não se importa de sacrificar um pouco de precisão, esta é a melhor resposta.
AttackingHobo
11
Eu não sei sobre "best" - Como mostrado em outra resposta, você pode obter outra aproximação muito boa em cinco ops + abs (cuja velocidade depende do seu arco / compilador, mas geralmente é sem ramificação). Se a tabela de pesquisa não estiver em cache, será muito mais lenta.