¿Hay alguna forma de escribir la función de registro (base 2)?
El lenguaje C tiene 2 funciones integradas - >>
1. logque es base e.
2. log10base 10;
Pero necesito la función de registro de la base 2. Cómo calcular esto.
¿Hay alguna forma de escribir la función de registro (base 2)?
El lenguaje C tiene 2 funciones integradas - >>
1. logque es base e.
2. log10base 10;
Pero necesito la función de registro de la base 2. Cómo calcular esto.
Respuestas:
Matemáticas simples:
log 2 ( x ) = log y ( x ) / log y (2)
donde y puede ser cualquier cosa, que para las funciones de registro estándar es 10 o e .
C99 tiene log2(así como log2fy log2lpara flotador y doble largo).
Si está buscando un resultado integral, puede simplemente determinar el conjunto de bits más alto en el valor y devolver su posición.
Integer.highestOneBit(int)método de 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. Pero como Java solo tiene entradas de 32 bits, está bien. Para C / C ++, debe tenerse en cuenta.
#define M_LOG2E 1.44269504088896340736 // log2(e)
inline long double log2(const long double x){
return log(x) * M_LOG2E;
}
(la multiplicación puede ser más rápida que la división)
Como se indica en http://en.wikipedia.org/wiki/Logarithm :
logb(x) = logk(x) / logk(b)
Lo que significa que:
log2(x) = log10(x) / log10(2)
log()implementación, no lo hará. Culpa mía.
log10()es una función definida en el estándar C, el compilador es libre de tratarla "especialmente", incluyendo precalcular el resultado, que creo que fue la sugerencia de @Johannes.
log10(2)con una constante.
Si desea hacerlo rápido, puede usar una tabla de búsqueda como en Bit Twiddling Hacks (solo 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];
Además, debe echar un vistazo a los métodos incorporados de sus compiladores, como _BitScanReversecuál podría ser más rápido porque puede calcularse completamente en hardware.
Eche un vistazo también a los posibles duplicados ¿Cómo hacer un log2 () entero en C ++?
uint16_t log2(uint32_t n) {//but truncated
if (n==0) throw ...
uint16_t logValue = -1;
while (n) {//
logValue++;
n >>= 1;
}
return logValue;
}
Básicamente lo mismo que el de tomlogic .
Tienes que incluir math.h (C) o cmath (C ++) Por supuesto, ten en cuenta que tienes que seguir las matemáticas que conocemos ... solo números> 0.
Ejemplo:
#include <iostream>
#include <cmath>
using namespace std;
int main(){
cout<<log2(number);
}
Necesitaba tener más precisión que solo la posición del bit más significativo, y el microcontrolador que estaba usando no tenía biblioteca matemática. Descubrí que solo usar una aproximación lineal entre 2 ^ n valores para argumentos de valor entero positivo funcionaba bien. Aquí está el 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));
}
En mi programa principal, necesitaba calcular N * log2 (N) / 2 con un resultado entero:
temp = (((uint32_t) N) * approx_log_base_2_N_times_256) / 512;
y los valores de 16 bits nunca se desviaron más del 2%
Todas las respuestas anteriores son correctas. Esta respuesta mía a continuación puede ser útil si alguien la necesita. He visto este requisito en muchas preguntas que estamos resolviendo usando C.
log2 (x) = logy (x) / logy (2)
Sin embargo, si está utilizando lenguaje C y desea que el resultado sea un número entero, puede utilizar lo siguiente:
int result = (int)(floor(log(x) / log(2))) + 1;
Espero que esto ayude.
Versión mejorada de lo que hizo Ustaman Sangat
static inline uint64_t
log2(uint64_t n)
{
uint64_t val;
for (val = 0; n > 1; val++, n >>= 1);
return val;
}