Có cách nào để viết hàm log (cơ số 2) không?
Ngôn ngữ C có 2 chức năng tích hợp - >>
1. log
nào là bazơ e.
2. log10
căn 10;
Nhưng tôi cần hàm log của cơ số 2. Làm thế nào để tính toán điều này.
Có cách nào để viết hàm log (cơ số 2) không?
Ngôn ngữ C có 2 chức năng tích hợp - >>
1. log
nào là bazơ e.
2. log10
căn 10;
Nhưng tôi cần hàm log của cơ số 2. Làm thế nào để tính toán điều này.
Câu trả lời:
Toán học đơn giản:
log 2 ( x ) = log y ( x ) / log y (2)
trong đó y có thể là bất kỳ thứ gì, đối với các hàm log tiêu chuẩn là 10 hoặc e .
C99 có log2
(cũng như log2f
và log2l
đối với phao và kép dài).
Nếu bạn đang tìm kiếm một kết quả tích phân, bạn chỉ có thể xác định bit cao nhất được đặt trong giá trị và trả về vị trí của nó.
Integer.highestOneBit(int)
phương pháp):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
. Nhưng vì Java chỉ có ints 32-bit, nên nó ổn. Đối với C / C ++, nó cần được xem xét.
#define M_LOG2E 1.44269504088896340736 // log2(e)
inline long double log2(const long double x){
return log(x) * M_LOG2E;
}
(phép nhân có thể nhanh hơn phép chia)
Như đã nêu trên http://en.wikipedia.org/wiki/Logarithm :
logb(x) = logk(x) / logk(b)
Có nghĩa là:
log2(x) = log10(x) / log10(2)
log()
triển khai nên nó sẽ không làm điều đó. Lỗi của tôi.
log10()
một chức năng được định nghĩa trong tiêu chuẩn C, trình biên dịch có thể tự do xử lý nó "đặc biệt", bao gồm tính toán trước kết quả, mà tôi tin rằng đó là gợi ý của @Johannes?
log10(2)
bằng một hằng số.
Nếu bạn muốn làm cho nó nhanh, bạn có thể sử dụng một bảng tra cứu như trong Bit Twiddling Hacks (chỉ số nguyên 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];
Ngoài ra, bạn nên xem xét các phương thức tích hợp trình biên dịch của mình như phương thức _BitScanReverse
nào có thể nhanh hơn vì nó có thể hoàn toàn được tính toán trong phần cứng.
Cũng hãy xem có thể trùng lặp Làm thế nào để thực hiện một số nguyên log2 () trong C ++?
log2(x) = log10(x) / log10(2)
uint16_t log2(uint32_t n) {//but truncated
if (n==0) throw ...
uint16_t logValue = -1;
while (n) {//
logValue++;
n >>= 1;
}
return logValue;
}
Về cơ bản giống như tomlogic của.
Bạn phải bao gồm math.h (C) hoặc cmath (C ++) Tất nhiên, hãy nhớ rằng bạn phải tuân theo các phép toán mà chúng ta biết ... chỉ các số> 0.
Thí dụ:
#include <iostream>
#include <cmath>
using namespace std;
int main(){
cout<<log2(number);
}
Tôi cần có độ chính xác cao hơn rằng vị trí của bit quan trọng nhất và bộ vi điều khiển tôi đang sử dụng không có thư viện toán học. Tôi thấy rằng chỉ cần sử dụng xấp xỉ tuyến tính giữa 2 ^ n giá trị cho các đối số giá trị nguyên dương là hoạt động tốt. Đây là mã:
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));
}
Trong chương trình chính của mình, tôi cần tính N * log2 (N) / 2 với kết quả là số nguyên:
temp = (((uint32_t) N) * khoảng_log_base_2_N_times_256) / 512;
và tất cả các giá trị 16 bit không bao giờ bị tắt quá 2%
Tất cả các câu trả lời trên đều đúng. Câu trả lời này của tôi dưới đây có thể hữu ích nếu ai đó cần nó. Tôi đã thấy yêu cầu này trong nhiều câu hỏi mà chúng tôi đang giải quyết bằng cách sử dụng C.
log2 (x) = logy (x) / logy (2)
Tuy nhiên, nếu bạn đang sử dụng ngôn ngữ C và bạn muốn kết quả là số nguyên, bạn có thể sử dụng như sau:
int result = (int)(floor(log(x) / log(2))) + 1;
Hi vọng điêu nay co ich.
Phiên bản cải tiến của những gì Ustaman Sangat đã làm
static inline uint64_t
log2(uint64_t n)
{
uint64_t val;
for (val = 0; n > 1; val++, n >>= 1);
return val;
}