2010-10-12 15 views
5

Necesito la utilidad de contador de bits en C++ que es capaz de contar el número del bit más significativo en un valor numérico constante y presentar este número como constante de tiempo de compilación.Metaprograma para el conteo de bits

sólo para asegurarse de que todo sea claro - número del bit más significativo para un conjunto de valores numéricos:

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

Soy nuevo en la programación plantilla, pero creo que esa es la forma.

Proporcione algunas muestras de código, cualquier ayuda sería apreciada.

+1

En otras palabras, es necesario 'piso (lg (n)) + 1', donde' lg' es el logaritmo de base 2. – outis

+1

¿Cuál sería el valor correcto para 0? –

+0

Sí, necesito exactamente 'floor (lg (n)) + 1'. '0' significa que no se requieren bits para almacenar este número, por lo que el resultado es 0 también. – Keynslug

Respuesta

12

Editar: He leído mal lo que querías.

Aquí es lo que quiere:

El número de bits significativos en 0 es 0.

El número de bits significativos en x es el número de bits significativos en x/2 más uno.

para que pueda obtener:

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++ siempre tiene algunas profundidades más profundas para mí. Increíble. –

+0

¡Bien! gran solución, pero supongo que debería editar la pregunta un poco. – Keynslug

+2

Esta plantilla proporciona el número de bits '1', pero no el número mínimo de bits necesarios para almacenar el valor. Para eso, debes reemplazar '(x% 2)' con '1'. –

1

Aquí está mi aplicación; menos elegante que el de @sepp2k, sigue un enfoque diferente, en realidad cuenta los bits y proporciona tanto la posición del MSB como el número de bits significativos.

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

Resultado de muestra:

[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 
Cuestiones relacionadas