Comment écrire la base de journal (2) dans c / c ++

Est-il possible d’écrire la fonction log (base 2)?

Le langage C a 2 fonctions intégrées – >>

1. log qui est la base e.

2. log10 base 10;

Mais j’ai besoin de la fonction log de base 2.Comment calculer cela.

Mathématiques simples:

log 2 ( x ) = log y ( x ) / log y (2)

y peut être n’importe quoi, qui pour les fonctions de journal standard est 10 ou e .

Si vous recherchez un résultat intégral, vous pouvez simplement déterminer le bit le plus élevé défini dans la valeur et renvoyer sa position.

 #define M_LOG2E 1.44269504088896340736 // log2(e) inline long double log2(const long double x){ return log(x) * M_LOG2E; } 

(la multiplication peut être plus rapide que la division)

C99 a log2 (ainsi que log2f et log2l pour float et long double).

Comme indiqué sur http://en.wikipedia.org/wiki/Logarithm :

 logb(x) = logk(x) / logk(b) 

Ce qui signifie que:

 log2(x) = log10(x) / log10(2) 
 log2(int n) = 31 - __builtin_clz(n) 

Si vous voulez faire vite, vous pouvez utiliser une table de consultation comme dans Bit Twiddling Hacks (entier log2 uniquement).

 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]; 

De plus, vous devriez jeter un oeil à vos méthodes intégrées de compilateurs telles que _BitScanReverse qui pourraient être plus rapides car elles peuvent être entièrement calculées en matériel.

Jetez également un oeil à la possibilité de dupliquer Comment faire un entier log2 () en 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; } 

Fondamentalement la même chose que celle de Tomlogic .

Vous devez inclure math.h (C) ou cmath (C ++) Bien sûr, gardez à l’esprit que vous devez suivre les calculs que nous connaissons … seulement des nombres> 0.

Exemple:

 #include  #include  using namespace std; int main(){ cout< 

Je devais avoir plus de précision que la position du bit le plus significatif, et le microcontrôleur que j’utilisais n’avait pas de bibliothèque mathématique. J’ai trouvé que l’utilisation d’une approximation linéaire entre 2 ^ n valeurs pour des arguments de valeur entière positive fonctionnait bien. Voici le code:

 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)); } 

Dans mon programme principal, je devais calculer N * log2 (N) / 2 avec un résultat entier:

temp = (((uint32_t) N) * approx_log_base_2_N_times_256) / 512;

et toutes les valeurs de 16 bits n'ont jamais été inférieures à 2%

Consultez votre cours de mathématiques de base, log n / log 2 . Peu importe si vous choisissez log ou log10 dans ce cas, la division par le log de la nouvelle base fait l’affaire.