Чи є спосіб написати функцію журналу (основа 2)?
Мова С має 2 вбудовані функції - >>
1. logщо є основою e.
2. log10основа 10;
Але мені потрібна функція журналу бази 2. Як це розрахувати.
Чи є спосіб написати функцію журналу (основа 2)?
Мова С має 2 вбудовані функції - >>
1. logщо є основою e.
2. log10основа 10;
Але мені потрібна функція журналу бази 2. Як це розрахувати.
Відповіді:
C99 має log2(як log2fі log2lдля поплавка, так і для довгих подвійних).
Якщо ви шукаєте інтегральний результат, ви можете просто визначити найвищий біт, встановлений у значенні, і повернути його положення.
Integer.highestOneBit(int)методу 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. Але оскільки Java має лише 32-розрядні ints, це нормально. Для C / C ++ це потрібно враховувати.
#define M_LOG2E 1.44269504088896340736 // log2(e)
inline long double log2(const long double x){
return log(x) * M_LOG2E;
}
(множення може бути швидшим, ніж ділення)
Як зазначено на http://en.wikipedia.org/wiki/Logarithm :
logb(x) = logk(x) / logk(b)
Це означає, що:
log2(x) = log10(x) / log10(2)
log()реалізації, він цього не зробить. Моє ліжко.
log10()функція визначена у стандарті С, компілятор може вільно обробляти її "спеціально", включаючи попередній обчислення результату, що, на мою думку, було пропозицією @Johannes?
log10(2)константою.
Якщо ви хочете зробити це швидко, ви можете скористатися пошуковою таблицею, як у розділі Bit Twiddling Hacks (лише цілочисельний журнал2 ).
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];
Крім того, вам слід поглянути на вбудовані у ваші компілятори методи, наприклад, _BitScanReverseякі можуть бути швидшими, оскільки вони можуть бути повністю обчислені в апаратному забезпеченні.
Погляньте також на можливий дублікат Як зробити цілочисельний log2 () в C ++?
uint16_t log2(uint32_t n) {//but truncated
if (n==0) throw ...
uint16_t logValue = -1;
while (n) {//
logValue++;
n >>= 1;
}
return logValue;
}
В основному те саме, що і tomlogic .
Ви повинні включити math.h (C) або cmath (C ++). Звичайно, майте на увазі, що ви повинні слідувати математиці, яку ми знаємо ... лише цифри> 0.
Приклад:
#include <iostream>
#include <cmath>
using namespace std;
int main(){
cout<<log2(number);
}
Мені потрібно було мати більшу точність, ніж лише положення найзначнішого біта, а мікроконтролер, яким я користувався, не мав математичної бібліотеки. Я виявив, що просто використання лінійного наближення між 2 ^ n значеннями для позитивних цілочисельних аргументів спрацювало добре. Ось код:
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));
}
У моїй основній програмі мені потрібно було обчислити N * log2 (N) / 2 із цілочисельним результатом:
temp = (((uint32_t) N) * approx_log_base_2_N_times_256) / 512;
і всі 16-бітові значення ніколи не відключалися більш ніж на 2%
Усі вищезазначені відповіді є правильними. Ця моя відповідь нижче може бути корисною, якщо вона комусь потрібна. Цю вимогу я бачив у багатьох питаннях, які ми вирішуємо за допомогою C.
log2 (x) = logy (x) / logy (2)
Однак, якщо ви використовуєте мову C і хочете отримати результат у цілому числі, ви можете використовувати наступне:
int result = (int)(floor(log(x) / log(2))) + 1;
Сподіваюся, це допомагає.