Existe alguma maneira de escrever a função de log (base 2)?
A linguagem C tem 2 funções integradas - >>
1. log
que é a base e.
2. log10
base 10;
Mas preciso da função log da base 2. Como calcular isso.
Existe alguma maneira de escrever a função de log (base 2)?
A linguagem C tem 2 funções integradas - >>
1. log
que é a base e.
2. log10
base 10;
Mas preciso da função log da base 2. Como calcular isso.
Respostas:
Matemática simples:
log 2 ( x ) = log y ( x ) / log y (2)
onde y pode ser qualquer coisa, que para funções de log padrão é 10 ou e .
C99 tem log2
(assim como log2f
e log2l
para float e long double).
Se você está procurando um resultado integral, pode apenas determinar o bit mais alto definido no valor e retornar sua posição.
Integer.highestOneBit(int)
método 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
. Mas, como o Java tem apenas ints de 32 bits, tudo bem. Para C / C ++, isso precisa ser considerado.
#define M_LOG2E 1.44269504088896340736 // log2(e)
inline long double log2(const long double x){
return log(x) * M_LOG2E;
}
(a multiplicação pode ser mais rápida do que a divisão)
Conforme declarado em http://en.wikipedia.org/wiki/Logarithm :
logb(x) = logk(x) / logk(b)
O que significa que:
log2(x) = log10(x) / log10(2)
log()
implementação, ele não o fará. Foi mal.
log10()
uma função é definida no padrão C, o compilador está livre para tratá-la "especialmente", incluindo pré-computar o resultado, o que acredito ter sido a sugestão de @Johannes?
log10(2)
por uma constante.
Se você quiser torná-lo mais rápido, você pode usar uma tabela de pesquisa como em Bit Twiddling Hacks (log2 inteiro apenas).
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];
Além disso, você deve dar uma olhada nos métodos embutidos do seu compilador, como o _BitScanReverse
qual pode ser mais rápido porque pode ser inteiramente computado em hardware.
Dê uma olhada também nas possíveis duplicatas. Como fazer um log2 () inteiro em C ++?
uint16_t log2(uint32_t n) {//but truncated
if (n==0) throw ...
uint16_t logValue = -1;
while (n) {//
logValue++;
n >>= 1;
}
return logValue;
}
Basicamente o mesmo do tomlogic .
Você tem que incluir math.h (C) ou cmath (C ++). Claro, lembre-se de que você deve seguir a matemática que conhecemos ... apenas números> 0.
Exemplo:
#include <iostream>
#include <cmath>
using namespace std;
int main(){
cout<<log2(number);
}
Eu precisava ter mais precisão do que apenas a posição do bit mais significativo, e o microcontrolador que estava usando não tinha biblioteca matemática. Descobri que apenas usar uma aproximação linear entre 2 ^ n valores para argumentos de valor inteiro positivo funcionou bem. Aqui está o código:
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));
}
Em meu programa principal, precisei calcular N * log2 (N) / 2 com um resultado inteiro:
temp = (((uint32_t) N) * approx_log_base_2_N_times_256) / 512;
e todos os valores de 16 bits nunca foram desativados em mais de 2%
Todas as respostas acima estão corretas. Esta minha resposta abaixo pode ser útil se alguém precisar dela. Eu vi esse requisito em muitas questões que estamos resolvendo usando C.
log2 (x) = logy (x) / logy (2)
No entanto, se estiver usando a linguagem C e quiser o resultado em número inteiro, você pode usar o seguinte:
int result = (int)(floor(log(x) / log(2))) + 1;
Espero que isto ajude.
Versão aprimorada do que Ustaman Sangat fez
static inline uint64_t
log2(uint64_t n)
{
uint64_t val;
for (val = 0; n > 1; val++, n >>= 1);
return val;
}