C'è un modo per scrivere la funzione log (base 2)?
Il linguaggio C ha 2 funzioni integrate - >>
1. logche è la base e.
2. log10base 10;
Ma ho bisogno della funzione logaritmica di base 2. Come calcolarla.
C'è un modo per scrivere la funzione log (base 2)?
Il linguaggio C ha 2 funzioni integrate - >>
1. logche è la base e.
2. log10base 10;
Ma ho bisogno della funzione logaritmica di base 2. Come calcolarla.
Risposte:
Matematica semplice:
log 2 ( x ) = log y ( x ) / log y (2)
dove y può essere qualsiasi cosa, che per le funzioni di log standard è 10 o e .
C99 ha log2(così come log2fe log2lper float e long double).
Se stai cercando un risultato integrale, puoi semplicemente determinare il bit più alto impostato nel valore e restituirne la posizione.
Integer.highestOneBit(int)metodo 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. Ma poiché Java ha solo int a 32 bit, va bene. Per C / C ++ deve essere considerato.
#define M_LOG2E 1.44269504088896340736 // log2(e)
inline long double log2(const long double x){
return log(x) * M_LOG2E;
}
(la moltiplicazione può essere più veloce della divisione)
Come affermato su http://en.wikipedia.org/wiki/Logarithm :
logb(x) = logk(x) / logk(b)
Che significa che:
log2(x) = log10(x) / log10(2)
log()dell'implementazione, non lo farà. Colpa mia.
log10()è una funzione definita nello standard C, il compilatore è libero di trattarla "appositamente", incluso il precalcolo del risultato, che credo sia stato il suggerimento di @Johannes?
log10(2)con una costante.
Se vuoi renderlo veloce, puoi usare una tabella di ricerca come in Bit Twiddling Hacks (solo log2 intero).
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];
Inoltre dovresti dare un'occhiata ai metodi incorporati del tuo compilatore come il _BitScanReversequale potrebbe essere più veloce perché può essere interamente calcolato in hardware.
Dai anche uno sguardo al possibile duplicato Come fare un intero log2 () in C ++?
uint16_t log2(uint32_t n) {//but truncated
if (n==0) throw ...
uint16_t logValue = -1;
while (n) {//
logValue++;
n >>= 1;
}
return logValue;
}
Fondamentalmente lo stesso di tomlogic .
Devi includere math.h (C) o cmath (C ++) Ovviamente tieni presente che devi seguire la matematica che conosciamo ... solo numeri> 0.
Esempio:
#include <iostream>
#include <cmath>
using namespace std;
int main(){
cout<<log2(number);
}
Avevo bisogno di avere più precisione che solo la posizione del bit più significativo e il microcontrollore che stavo usando non aveva una libreria matematica. Ho scoperto che il solo utilizzo di un'approssimazione lineare tra 2 ^ n valori per argomenti con valori interi positivi ha funzionato bene. Ecco il codice:
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));
}
Nel mio programma principale, avevo bisogno di calcolare N * log2 (N) / 2 con un risultato intero:
temp = (((uint32_t) N) * approx_log_base_2_N_times_256) / 512;
e tutti i valori a 16 bit non sono mai stati off di oltre il 2%
Tutte le risposte precedenti sono corrette. Questa mia risposta di seguito può essere utile se qualcuno ne ha bisogno. Ho visto questo requisito in molte domande che stiamo risolvendo utilizzando C.
log2 (x) = logy (x) / logy (2)
Tuttavia, se stai usando il linguaggio C e vuoi il risultato in numero intero, puoi usare quanto segue:
int result = (int)(floor(log(x) / log(2))) + 1;
Spero che questo ti aiuti.
Versione migliorata di ciò che ha fatto Ustaman Sangat
static inline uint64_t
log2(uint64_t n)
{
uint64_t val;
for (val = 0; n > 1; val++, n >>= 1);
return val;
}