2010-10-12 15 views
5

Ho bisogno di un bit counter utility in C++ che sia in grado di contare il numero del bit più significativo in un valore numerico costante e di presentare questo numero come costante in fase di compilazione.Metaprogram per il conteggio dei bit

Proprio per rendere tutto chiaro - numero di bit più significativo per un insieme di valori numerici:

255 => 8 (11111111b) 
    7 => 3 (111b) 
1024 => 11 (10000000000b) 
    26 => 5 (11010b) 

io sono nuovo alla programmazione modello, ma penso che sia il modo.

Si prega di fornire alcuni esempi di codice, ogni aiuto sarebbe apprezzato.

+1

In altre parole, è necessario 'piano (lg (n)) + 1', dove' lg' è il logaritmo in base 2. – outis

+1

Quale sarebbe il valore corretto per 0? –

+0

Sì, ho bisogno esattamente di 'floor (lg (n)) + 1'. '0' significa che non sono necessari bit per memorizzare questo numero, pertanto anche il risultato è 0. – Keynslug

risposta

12

Modifica: ho completamente letto male ciò che volevi.

Ecco ciò che si vuole:

Il numero di bit significativi 0 è 0.

Il numero di bit significativi x è il numero di bit significativi in ​​x/2 più uno.

in modo da ottenere:

template <unsigned int x> 
struct SignificantBits { 
    static const unsigned int n = SignificantBits<x/2>::n + 1; 
}; 

template <> 
struct SignificantBits<0> { 
    static const unsigned int n = 0; 
}; 
+0

C++ ha sempre delle profondità per me. Eccezionale. –

+0

OK! ottima soluzione, ma presumo che dovrei modificare la domanda un po '. – Keynslug

+2

Questo modello indica il numero di bit '1', ma non il numero minimo di bit necessari per memorizzare il valore. Per questo, devi sostituire '(x% 2)' con '1'. –

1

Ecco la mia attuazione; meno elegante di quello di @ sepp2k, segue un approccio diverso, contando effettivamente i bit e fornendo sia la posizione dell'MSB che il numero di bit significativi.

#include <iostream> 
#include <limits> 

// Number: the number to be examined; Bit: parameter used internally to specify the bit to 
// examine (the work starts from the leftmost bit) 
template<unsigned int Number, unsigned int Bit=std::numeric_limits<unsigned int>::digits-1> 
class BitCounter 
{ 
public: 
    // Most Significant Bit number; if it's the current, fine, otherwise 
    // delegate the work to another template that will examine the next bit 
    static const int MSB=(Number&(1<<Bit))?Bit:BitCounter<Number,Bit-1>::MSB; 
    // Count of significant bits - actually, MSB+1 
    static const int Count=MSB+1; 
}; 

// Corner case: we reached the first bit 
template<unsigned int Number> 
class BitCounter<Number,0> 
{ 
public: 
    // If it's 1, the MSB is the bit 0 (the rightmost), while if it's 0 it's "one before"; 
    // this is somewhat arbitrary to make Count get 0 for 0 and 1 for 1, you may want to 
    // change it just to 0 
    static const int MSB=Number==0?-1:0; 
    static const int Count=MSB+1; 
}; 

int main() 
{ 
    std::cout<<BitCounter<255>::Count<<" " 
      <<BitCounter<7>::Count<<" " 
      <<BitCounter<1024>::Count<<" " 
      <<BitCounter<26>::Count<<" " 
      <<BitCounter<1>::Count<<" " 
      <<BitCounter<0>::Count<<std::endl; 
    return 0; 
} 

Esempio di output:

[email protected]:~/cpp$ g++ tpl_bitcount.cpp -Wall -Wextra -ansi -pedantic -O3 -o tpl_bitcount.x && ./tpl_bitcount.x 
8 3 11 5 1 0 
Problemi correlati