web-dev-qa-db-fra.com

Comment écrire log base (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 de journalisation de la base 2.Comment calculer cela.

88
russell

Mathématiques simples:

bûche2 (x) = logy (x)/logy (2)

y peut être n'importe quoi, ce qui pour les fonctions de journalisation standard est 10 ou e.

183
Adam Crume

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.

51
tomlogic

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

49
Matthew Flaschen
#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)

40
logicray
log2(int n) = 31 - __builtin_clz(n)
13
w00t

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

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

Ce qui signifie que:

log2(x) = log10(x) / log10(2)
9
Patrick

Si vous voulez faire vite, vous pouvez utiliser une table de correspondance comme dans Bit Twiddling Hacks (entier uniquement 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];

De plus, vous devriez jeter un coup d'œil aux méthodes intégrées de vos compilateurs comme _BitScanReverse qui pourrait être plus rapide car il peut être entièrement calculé en matériel.

Regardez aussi les doublons possibles Comment faire un entier log2 () en C++?

8
bkausbk
log2(x) = log10(x) / log10(2)
2
the_void

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

Exemple:

#include <iostream>
#include <cmath>
using namespace std;

int main(){
    cout<<log2(number);
}
2
user2143904
uint16_t log2(uint32_t n) {//but truncated
     if (n==0) throw ...
     uint16_t logValue = -1;
     while (n) {//
         logValue++;
         n >>= 1;
     }
     return logValue;
 }

Fondamentalement identique à tomlogic .

2
Ustaman Sangat

J'avais besoin de 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 le simple fait d'utiliser une approximation linéaire entre 2 ^ n valeurs pour des arguments de valeur entière positive a bien fonctionné. 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, j'avais besoin de 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 16 bits n'ont jamais été décalées de plus de 2%

1
David Reinagel

Consultez votre cours de base en mathématiques, log n / log 2. Peu importe que vous choisissiez log ou log10dans ce cas, diviser par le log de la nouvelle base fait l'affaire.

0
Pieter

Version améliorée de ce qu'Ustaman Sangat a fait

static inline uint64_t
log2(uint64_t n)
{
    uint64_t val;
    for (val = 0; n > 1; val++, n >>= 1);

    return val;
}
0
Rian Quinn