2010-10-12 17 views
5

C++ 'da sayısal bir sabit değerdeki en anlamlı bit sayısını sayabilen ve bu sayıyı derleme zamanı sabiti olarak sunabilen bit sayacı yardımcı programına ihtiyacım var.Bit sayımı için metaprogram

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

Ben şablon programlama yeniyim ama bu şekilde olduğunu düşünüyorum: sayısal değerler kümesi için en önemli bit sayısını -

Hemen her şeyi açıklığa kavuşturmak.

Lütfen bazı kod örnekleri verin, herhangi bir yardım için teşekkür ederiz.

+1

, gereken lg' tabanı 2 logaritmasıdır '' kat (lg (n)) '+ 1',. – outis

+1

0 için doğru değer ne olurdu? –

+0

Evet, tam olarak zemine (lg (n)) + 1 'ihtiyacım var. '0', bu sayıyı saklamak için gerekli hiçbir bit anlamına gelmez, dolayısıyla sonuç 0 olur. – Keynslug

cevap

12

Düzenleme: Ne istediğini tamamen yanlış okudum.

Burada istediği bu: 0 içinde

önemli bit sayısı 0.

x önemli bitlerin sayısı x/2 artı bir önemli bit sayısıdır olduğunu.

Yani olsun:

İşte
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++ her zaman benim için daha derin derinliklere sahiptir. Muhteşem. –

+0

Tamam! Harika bir çözüm, ama sanırım soruyu biraz değiştirmem gerekiyor. – Keynslug

+2

Bu şablon, "1" bitlerinin sayısını verir, ancak değeri depolamak için gereken minimum bit sayısını değil. Bunun için '(x% 2)' yi '1 ile değiştirmelisiniz. –

1

benim uygulanması var; sepp2k'inkinden daha az zariftir, aslında bitleri saymayı ve MSB'nin konumunu ve anlamlı bitlerin sayısını sağlayarak farklı bir yaklaşımı izler.

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

Örnek çıktı: Diğer bir deyişle

[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