Untuk perhitungan bola mata, logaritma basis 2 mendekati sama dengan logaritma basis 10 ditambah dengan logaritma natural. Jelas lebih baik untuk menulis versi yang lebih akurat (dan lebih cepat) dalam sebuah program.
David Thornley
Untuk bilangan bulat, Anda dapat melakukan loop pada bitshift kanan, dan berhenti ketika mencapai 0. Jumlah loop adalah perkiraan dari log
Ada juga metode bit-twiddling yang bagus untuk ini (diambil dari Integer.highestOneBit(int)metode Java ):i |= (i >> 1); i |= (i >> 2); i |= (i >> 4); i |= (i >> 8); i |= (i >> 16); return i - (i >>> 1);
Joey
38
... atauwhile (i >>= 1) { ++l; }
Lee Daniel Crocker
2
@ Joey Itu akan bekerja dengan asumsi integer adalah 32 bit lebar, bukan? Untuk 64 bit itu akan memiliki ekstra i>>32. Tetapi karena Java hanya memiliki int 32-bit, itu baik-baik saja. Untuk C / C ++ perlu dipertimbangkan.
Perhatikan bahwa Anda dapat menghitung sebelumnya log10 (2) untuk meningkatkan kinerja.
corsiKa
@Johannes: Saya ragu kompilator akan menghitung log10 sebelumnya (2). Kompilator tidak tahu bahwa log10 akan mengembalikan nilai yang sama setiap saat. Untuk semua kompilator tahu, log10 (2) bisa mengembalikan nilai yang berbeda pada panggilan berturut-turut.
abelenky
@abelenky: Oke, saya ambil kembali. Karena kompilator tidak pernah melihat sumber log()implementasi , kompilator tidak akan melakukannya. Salahku.
Joey
3
@abelenky: Karena log10()fungsi didefinisikan dalam standar C, kompilator bebas untuk memperlakukannya "khusus", termasuk menghitung sebelumnya hasilnya, yang saya percaya adalah saran @Johannes?
caf
1
@CarlNorum: Saya baru saja memeriksa, dan gcc 4.7 setidaknya mengganti log10(2)dengan sebuah konstanta.
caf
8
Jika Anda ingin membuatnya cepat, Anda dapat menggunakan tabel pencarian seperti di Bit Twiddling Hacks (hanya integer log2).
uint32_t v;// find the log base 2 of 32-bit vint r;// result goes herestaticconstintMultiplyDeBruijnBitPosition[32]={0,9,1,10,13,21,2,29,11,14,16,18,22,25,3,30,8,12,20,28,15,17,24,7,19,27,23,6,26,5,4,31};
v |= v >>1;// first round down to one less than a power of 2
v |= v >>2;
v |= v >>4;
v |= v >>8;
v |= v >>16;
r =MultiplyDeBruijnBitPosition[(uint32_t)(v *0x07C4ACDDU)>>27];
Selain itu, Anda harus melihat metode builtin kompiler Anda seperti _BitScanReverseyang bisa lebih cepat karena dapat sepenuhnya dihitung dalam perangkat keras.
Mengapa perkalian dan pencarian tabel di bagian akhir? Tidak bisakah Anda melakukan (v + 1) yang akan membulatkan ke pangkat dua berikutnya? Dan kemudian, Anda dapat menggeser ke kanan satu per satu untuk membulatkan ke pangkat 2. berikutnya
Safayet Ahmed
@SafayetAhmed Jelaskan bagaimana Anda ingin mencari log2 dari sebuah angka dengan metode itu. Saya tidak tahu cara yang lebih mudah untuk mendapatkan nilai itu. Selain menggunakan aritmatika di atas dengan tabel pencarian, seseorang dapat menggunakan algoritma iteratif / rekursif atau menggunakan perangkat keras khusus / bawaan untuk melakukan perhitungan.
bkausbk
Katakanlah bit dari variabel 32 bit v diberi nomor 0 (LSB) melalui N (MSB). Katakanlah set bit paling signifikan dari v adalah n. Apakah benar jika dikatakan bahwa n mewakili lantai (log2 (v))? Apakah Anda tidak tertarik hanya menemukan n diberikan v?
Safayet Ahmed
Saya menyadari bahwa apa yang saya jelaskan hanya akan memberi Anda pangkat 2 terendah terdekat dan bukan logaritma sebenarnya. Perkalian dan pencarian tabel untuk beralih dari pangkat dua ke logaritma. Anda menggeser jumlah 0x07C4ACDD yang tersisa. Jumlah yang Anda geser ke kiri akan bergantung pada kekuatan dua. Jumlahnya sedemikian rupa, sehingga setiap urutan 5 bit yang berurutan adalah unik. (0000 0111 1100 0100 0110 1100 1101 1101) memberikan Anda urutan (00000) (00001) ... (11101). Bergantung pada seberapa jauh Anda bergeser, Anda mendapatkan salah satu dari pola 5-bit ini. Kemudian pencarian tabel. Sangat bagus.
Ada beberapa hal yang salah dengan solusi ini, tetapi secara umum, ini bagus jika Anda ingin menghindari floating point. Anda mengandalkan overflow agar ini berfungsi karena Anda menginisialisasi integer unsigned dengan -1. Ini bisa diperbaiki dengan menginisialisasi ke 0 dan kemudian mengembalikan nilai - 1, dengan asumsi Anda memeriksa kasus 0, yang Anda lakukan. Masalah lainnya adalah Anda mengandalkan loop yang berhenti ketika n == 0, yang harus Anda nyatakan secara eksplisit. Selain itu, ini bagus jika Anda ingin menghindari floating point.
Rian Quinn
2
Anda harus memasukkan math.h (C) atau cmath (C ++) Tentu perlu diingat bahwa Anda harus mengikuti matematika yang kita tahu ... hanya angka> 0.
Saya perlu memiliki ketepatan yang lebih dari hanya posisi bit yang paling signifikan, dan mikrokontroler yang saya gunakan tidak memiliki perpustakaan matematika. Saya menemukan bahwa hanya menggunakan pendekatan linier antara nilai 2 ^ n untuk argumen nilai integer positif bekerja dengan baik. Ini kodenya:
Semua jawaban di atas benar. Jawaban saya di bawah ini dapat membantu jika seseorang membutuhkannya. Saya telah melihat persyaratan ini dalam banyak pertanyaan yang kami selesaikan menggunakan C.
log2 (x) = logy (x) / logy (2)
Namun, jika Anda menggunakan bahasa C dan ingin hasilnya berupa bilangan bulat, Anda dapat menggunakan yang berikut ini:
Konsultasikan kursus matematika dasar Anda log n / log 2,. Tidak masalah apakah Anda memilih logatau log10dalam hal ini, membagi dengan logpangkalan baru melakukan triknya.
Jawaban:
Matematika sederhana:
log 2 ( x ) = log y ( x ) / log y (2)
di mana y bisa berupa apa saja, yang untuk fungsi log standar adalah 10 atau e .
sumber
C99 memiliki
log2
(sertalog2f
danlog2l
untuk float dan long double).sumber
Jika Anda mencari hasil integral, Anda dapat menentukan kumpulan bit tertinggi dalam nilai dan mengembalikan posisinya.
sumber
Integer.highestOneBit(int)
metode Java ):i |= (i >> 1); i |= (i >> 2); i |= (i >> 4); i |= (i >> 8); i |= (i >> 16); return i - (i >>> 1);
while (i >>= 1) { ++l; }
i>>32
. Tetapi karena Java hanya memiliki int 32-bit, itu baik-baik saja. Untuk C / C ++ perlu dipertimbangkan.(perkalian mungkin lebih cepat dari pembagian)
sumber
sumber
Seperti yang dinyatakan di http://en.wikipedia.org/wiki/Logarithm :
Artinya:
sumber
log()
implementasi , kompilator tidak akan melakukannya. Salahku.log10()
fungsi didefinisikan dalam standar C, kompilator bebas untuk memperlakukannya "khusus", termasuk menghitung sebelumnya hasilnya, yang saya percaya adalah saran @Johannes?log10(2)
dengan sebuah konstanta.Jika Anda ingin membuatnya cepat, Anda dapat menggunakan tabel pencarian seperti di Bit Twiddling Hacks (hanya integer log2).
Selain itu, Anda harus melihat metode builtin kompiler Anda seperti
_BitScanReverse
yang bisa lebih cepat karena dapat sepenuhnya dihitung dalam perangkat keras.Perhatikan juga kemungkinan duplikat Bagaimana melakukan integer log2 () di C ++?
sumber
sumber
Pada dasarnya sama dengan tomlogic .
sumber
Anda harus memasukkan math.h (C) atau cmath (C ++) Tentu perlu diingat bahwa Anda harus mengikuti matematika yang kita tahu ... hanya angka> 0.
Contoh:
sumber
Saya perlu memiliki ketepatan yang lebih dari hanya posisi bit yang paling signifikan, dan mikrokontroler yang saya gunakan tidak memiliki perpustakaan matematika. Saya menemukan bahwa hanya menggunakan pendekatan linier antara nilai 2 ^ n untuk argumen nilai integer positif bekerja dengan baik. Ini kodenya:
Dalam program utama saya, saya perlu menghitung N * log2 (N) / 2 dengan hasil integer:
suhu = (((uint32_t) N) * perkiraan_log_base_2_N_times_256) / 512;
dan semua nilai 16 bit tidak pernah turun lebih dari 2%
sumber
Semua jawaban di atas benar. Jawaban saya di bawah ini dapat membantu jika seseorang membutuhkannya. Saya telah melihat persyaratan ini dalam banyak pertanyaan yang kami selesaikan menggunakan C.
log2 (x) = logy (x) / logy (2)
Namun, jika Anda menggunakan bahasa C dan ingin hasilnya berupa bilangan bulat, Anda dapat menggunakan yang berikut ini:
Semoga ini membantu.
sumber
Konsultasikan kursus matematika dasar Anda
log n / log 2
,. Tidak masalah apakah Anda memilihlog
ataulog10
dalam hal ini, membagi denganlog
pangkalan baru melakukan triknya.sumber
Versi perbaikan dari apa yang dilakukan Ustaman Sangat
sumber