Apakah ada fungsi sinus yang lebih cepat?

25

Saya sedang mengerjakan noise 3D perlin generasi. Pustaka C # Math sepertinya membutuhkan banyak tenaga untuk apa yang saya butuhkan karena sebagian besar fungsinya menggunakan double percision. Saya menggunakan Math.Sin () di beberapa tempat untuk menghasilkan suara. Adakah yang tahu fungsi sinus yang lebih cepat?

pengguna2709
sumber

Jawaban:

32

Anda dapat menggunakan parabola untuk mengaproksimasi nilai fungsi sinus. Ini memiliki keuntungan memiliki akar tepat pada -pi / 2 dan pi / 2 yang biasanya tidak terjadi dengan perkiraan cepat lainnya berdasarkan TaylorSeries atau 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));
} 

Berikut ini adalah perbandingan dengan fungsi sinus yang sebenarnya:

teks alternatif

zfedoran
sumber
3
Ini memang solusi yang bagus. Berikut ini adalah artikel yang sangat bagus dari devmaster.net yang menjelaskan mengapa ini bekerja dan memberikan beberapa detail implementasi: devmaster.net/forums/showthread.php?t=5784
reverbb
Saya tidak tahu tentang C #, tetapi fungsi abs () di sebagian besar lingkungan C kemungkinan akan lebih cepat daripada cabang (operator?:), Ketika dioptimalkan.
3
Saya menghapus panggilan Math.Abs ​​() karena saya berasumsi bahwa kode ini mungkin berjalan di Xbox 360 atau Windows Phone 7. Kompiler JIT di Xbox 360 tidak sebaris apa pun. Panggilan ke Math.Abs ​​() sebenarnya lebih mahal.
zfedoran
@reverbb Link adalah 404. Ini adalah salinan yang di-cache.
Daniel Pendergast
1
@zfedoran Mengapa Anda meniadakan nilai kembali? Tampaknya menjadi gelombang sinus negatif.
Daniel Pendergast
12

Berapa kisaran nilai input untuk fungsi sin () Anda ? Untuk apa Anda menggunakannya, sepertinya mereka mungkin terbatas, yang berarti Anda dapat melakukan pre-compute nilai-nilainya . Misalnya, jika Anda mengumpulkan nilai input ke tingkat terdekat, maka Anda hanya memiliki 360 nilai yang mungkin - cukup pra-hitung dan simpan dalam tabel.

Jika Anda membutuhkan nilai yang sedikit lebih banyak, katakan ke satu tempat desimal, Anda dapat menginterpolasi dari tabel - Saya tidak terbiasa dengan perlin noise , tetapi kata "noise" tampaknya mengindikasikan bahwa ia tidak memerlukan akurasi yang tinggi. :) (Anda juga bisa membuat tabel yang lebih besar, 3600 entri tidak banyak ruang).

Cyclops
sumber
3
Jika kecepatan adalah perhatian utama Anda, dan Anda tidak keberatan mengorbankan sedikit keakuratan, ini adalah jawaban terbaik.
AttackingHobo
1
Saya tidak tahu tentang "terbaik" - Seperti yang ditunjukkan dalam jawaban lain, Anda bisa mendapatkan perkiraan lain yang sangat baik dalam lima operasi + abs (kecepatannya tergantung pada lengkungan / kompiler Anda, tetapi seringkali tanpa cabang). Jika tabel pencarian tidak ada dalam cache, itu akan jauh lebih lambat.