Apakah ada cara untuk menulis fungsi log (basis 2)?
Bahasa C memiliki 2 fungsi bawaan - >>
1. logyang merupakan basis e.
2. log10basis 10;
Tapi saya membutuhkan fungsi log basis 2. Bagaimana menghitung ini.
Apakah ada cara untuk menulis fungsi log (basis 2)?
Bahasa C memiliki 2 fungsi bawaan - >>
1. logyang merupakan basis e.
2. log10basis 10;
Tapi saya membutuhkan fungsi log basis 2. Bagaimana menghitung ini.
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 .
C99 memiliki log2(serta log2fdan log2luntuk float dan long double).
Jika Anda mencari hasil integral, Anda dapat menentukan kumpulan bit tertinggi dalam nilai dan mengembalikan posisinya.
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.
#define M_LOG2E 1.44269504088896340736 // log2(e)
inline long double log2(const long double x){
return log(x) * M_LOG2E;
}
(perkalian mungkin lebih cepat dari pembagian)
Seperti yang dinyatakan di http://en.wikipedia.org/wiki/Logarithm :
logb(x) = logk(x) / logk(b)
Artinya:
log2(x) = log10(x) / log10(2)
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).
uint32_t v; // find the log base 2 of 32-bit v
int r; // result goes here
static const int MultiplyDeBruijnBitPosition[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.
Perhatikan juga kemungkinan duplikat Bagaimana melakukan integer log2 () di C ++?
uint16_t log2(uint32_t n) {//but truncated
if (n==0) throw ...
uint16_t logValue = -1;
while (n) {//
logValue++;
n >>= 1;
}
return logValue;
}
Pada dasarnya sama dengan tomlogic .
Anda harus memasukkan math.h (C) atau cmath (C ++) Tentu perlu diingat bahwa Anda harus mengikuti matematika yang kita tahu ... hanya angka> 0.
Contoh:
#include <iostream>
#include <cmath>
using namespace std;
int main(){
cout<<log2(number);
}
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:
uint16_t approx_log_base_2_N_times_256(uint16_t n)
{
uint16_t msb_only = 0x8000;
uint16_t exp = 15;
if (n == 0)
return (-1);
while ((n & msb_only) == 0) {
msb_only >>= 1;
exp--;
}
return (((uint16_t)((((uint32_t) (n ^ msb_only)) << 8) / msb_only)) | (exp << 8));
}
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%
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:
int result = (int)(floor(log(x) / log(2))) + 1;
Semoga ini membantu.
Versi perbaikan dari apa yang dilakukan Ustaman Sangat
static inline uint64_t
log2(uint64_t n)
{
uint64_t val;
for (val = 0; n > 1; val++, n >>= 1);
return val;
}