Saya mencoba menerapkan titik tetap rutin yang melibatkan menghitung nilai untuk kecil yang mendekati . Arsitektur target adalah FPGA. Satu masalah adalah bahwa fungsi ini tidak cocok dengan penggunaan ekspansi Taylor. Kita dapat melihat bahwa untuk nilai x yang kecil, kemiringan berubah hingga tak terhingga ketika mendekati , oleh karena itu mengevaluasi fungsi menggunakan rangkaian daya melibatkan mengalikan koefisien besar dengan kecil . Karenanya metode ini secara numerik tidak stabil.
Menggunakan pendekatan iteratif, Newton-Raphson menghasilkan persamaan iteratif berikut: , di mana kita berada mencoba memperkirakan . Tetapi sekali lagi, karena kecil, juga harus kecil untuk solusi untuk bertemu. Karena persamaan melibatkan membagi angka kecil dengan angka kecil lainnya, kemungkinan aritmatika titik tetap akan gagal.
Dengan itu, saya ingin tahu bagaimana menerapkan pendekatan nilai kecil untuk menggunakan aritmatika titik tetap, baik menggunakan koefisien yang telah dikomputasi atau metode iteratif.
Jawaban:
Sebuah rutinitas yang telah saya gunakan sebelumnya (saya tidak tahu apakah itu "tepat" atau tidak) adalah pendekatan membagi dan menaklukkan.
Anda mulai dengan nilai sewenang-wenang atas dan bawah (katakan masing-masing 5 dan 0 - akar kuadrat tertinggi dan terendah yang ingin Anda temukan) dan temukan titik tengah di antara mereka. Kuadratkan nilai itu.
Jika nilai kuadrat lebih besar dari target Anda, tetapkan nilai atas menjadi nilai kuadrat Anda. Jika lebih rendah, atur nilai yang lebih rendah.
Ulangi sampai nilai kuadrat cocok dengan nilai pencarian Anda, atau Anda telah menjalankan iterasi yang cukup seakurat yang Anda inginkan.
Berikut ini adalah versi kecil yang telah saya ketuk bersama di perl:
Ini tentu saja menggunakan floating point, tetapi dapat dengan mudah ditambahkan ke titik tetap. Anda dapat memvariasikan keakuratan dengan mengubah batas iterasi. Setiap iterasi menjadi sedikit lebih akurat daripada yang sebelumnya.
misal: - cari akar kuadrat dari 9:
Jika sudah menemukan nilai 3 tentu saja akan berhenti lebih awal.
Berikan iterasi yang cukup dan itu harus membuatnya sangat akurat:
sumber
Berikut adalah beberapa ide dan rutinitas dari guru transenden / Guru Scott Dattalo di sini .
Itu tentu saja lelucon kecuali bagian guru (Guru?). Scott luar biasa.
Diskusi yang relevan. 2005 & PIC dan beberapa bernilai C tetapi mungkin bernilai.
Scott lagi - 2003
Dua Tuan !!!
Dattallo & Golovchenko.
Berbagai metode
sumber
Anda tidak menentukan apa yang Anda maksud dengan "nilai kecil", atau "perkiraan". Jadi apa yang akan saya usulkan mungkin tidak berhasil, tapi begini saja.
Hal yang paling mudah adalah dengan melihat-lihat. Pada dasarnya ROM di mana bus alamat adalah nomor yang Anda inginkan dengan root-square, dan hasilnya adalah data. Dengan BRAM tunggal, Anda bisa melakukan 9 bit, 8 bit LUT. Tentu saja, lebih banyak BRAM akan memberi Anda meja yang lebih besar.
(BRAM = Istilah Xilinx untuk RAM Blok, yang juga dapat digunakan sebagai ROM. FPGA lain memiliki hal serupa.)
Jika Anda ingin lebih presisi daripada yang diberikan BRAM, Anda bisa melakukan interpolasi linier sederhana dari dua entri LUT. Sebagai contoh, katakanlah Anda menginginkan input 12-bit, tetapi Anda hanya memiliki BRAM untuk 10 bit. Anda mengambil 10 bit teratas dari input Anda dan mencarinya di LUT. Tambahkan 1 ke 10 bit itu dan cari nilainya juga. Anda kemudian melakukan interpolasi linier sederhana antara dua hasil, menggunakan 2 bit terbawah untuk memberi tahu Anda proporsi satu nilai di atas yang lain. Tentu saja ini hanya akan memberi Anda perkiraan, tetapi saya pikir jika Anda menghitung, Anda akan menemukan bahwa itu mungkin cukup baik.
Metode ini adalah yang paling tidak akurat dengan angka bernilai rendah, tetapi saat input masuk ke nilai yang lebih tinggi, akurasi meningkat.
Optimalisasi metode di atas adalah dengan menggunakan BRAM sebagai ROM dual-port. Dengan cara ini Anda dapat membaca dua nilai tanpa menambah jumlah yang digunakan BRAM. Ini juga akan memungkinkan Anda untuk menghitung SQRT untuk setiap siklus clock, dengan beberapa penundaan perpipaan.
Kebetulan, metode ini juga berfungsi untuk SINE / COSINE juga!
sumber
Coba pendekatan berikut
x <<= 2
dalam C) hingga berada dalam kisaran di atas.sumber
Mencobax = ( y+ d)2≈y2+ 2 dy
jadi biarkan d= ( x -y2) / 2 y= ( x / y- y) ≫ 1
dan selanjutnya y= y+ d.
Jika MSb adalah n dari kanan, biarkan duluy= 1 ≪ ( n / 2 ) . Berkonvergensi dalam <4 iterasi.
sumber
Coba: tebakan yang lebih baik untuk variabel 1
Nomor Anda dapat dianggap: A * 2 ^ n
Perkiraan pertama adalah: A * 2 ^ (n / 2)
Katakanlah Anda menggunakan angka 32-bit, dengan 24 bit digunakan untuk menyimpan pecahan. Untuk angka> 1:
1. Hitung jumlah bit yang digunakan dalam bagian integer (N)
2. Membagi dua angka ini (N '= N / 2, mis. Bergeser ke kanan 1 bit)
3. Geser ke kanan angka asli dengan N' : ini adalah tebakan pertama Anda.
Dalam format ini, jumlah terkecil yang dapat Anda miliki adalah 2 ^ -24. Root kuadrat akan ba sekitar 2 ^ -12. Jadi, untuk angka <1:
1. Hitung jumlah bit "nol" di dalam fraksi, hingga Anda mencapai bit yang ditentukan (N)
2. Membagi dua angka ini (N '= N / 2, mis. Kanan bergeser 1 bit)
3. KIRI menggeser nomor asli dengan jumlah yang direvisi: ini adalah tebakan pertama Anda.
Contoh:
0,0000 0000 0000 0000 1 [16 angka nol terkemuka] kira-kira sama dengan: 0,0000 0000 1
Akhirnya, jika Anda masih memiliki masalah dengan A kecil: dapatkah Anda menghitung 1 / A?
Jika demikian, maka balikkan nomor Anda, lalu coba gunakan algoritma Inverse Square Root:
x' = 0.5x * (3 - Ax^2)
sumber