convert binary to decimal in template at compiler time.

Discussion in 'C++' started by Leo jay, Sep 12, 2007.

  1. Leo jay

    Leo jay Guest

    i'd like to implement a class template to convert binary numbers to
    decimal at compile time.
    and my test cases are:

    BOOST_STATIC_ASSERT((bin<1111,1111,1111,1111>::value == 65535));
    BOOST_STATIC_ASSERT((bin<1111>::value == 15));
    BOOST_STATIC_ASSERT((bin<0>::value == 0));
    BOOST_STATIC_ASSERT((bin<1010, 0011>::value == 163));

    you can find my implementation at:
    http://pastebin.org/2271

    the first three cases were ok, but the last one failed, because,
    compiler will parse 0011
    as a octal number 9, instead of decimal number 11 because of the
    leading 0s.

    to resolve this, i defined 4 macros:

    #define BIN1(a) bin<9##a>::value
    #define BIN2(a, b) bin<9##a, 9##b>::value
    #define BIN3(a, b, c) bin<9##a, 9##b, 9##c>::value
    #define BIN4(a, b, c, d) bin<9##a, 9##b, 9##c, 9##d>::value

    these macros could pass the last test case, but it's not good enough
    that i have to specify how many numbers i will input.

    is there any elegant way to resolve this?

    thanks in advance.
     
    Leo jay, Sep 12, 2007
    #1
    1. Advertising

  2. Leo jay

    Jim Langston Guest

    "Leo jay" <> wrote in message
    news:...
    > i'd like to implement a class template to convert binary numbers to
    > decimal at compile time.
    > and my test cases are:
    >
    > BOOST_STATIC_ASSERT((bin<1111,1111,1111,1111>::value == 65535));
    > BOOST_STATIC_ASSERT((bin<1111>::value == 15));
    > BOOST_STATIC_ASSERT((bin<0>::value == 0));
    > BOOST_STATIC_ASSERT((bin<1010, 0011>::value == 163));
    >
    > you can find my implementation at:
    > http://pastebin.org/2271
    >
    > the first three cases were ok, but the last one failed, because,
    > compiler will parse 0011
    > as a octal number 9, instead of decimal number 11 because of the
    > leading 0s.
    >
    > to resolve this, i defined 4 macros:
    >
    > #define BIN1(a) bin<9##a>::value
    > #define BIN2(a, b) bin<9##a, 9##b>::value
    > #define BIN3(a, b, c) bin<9##a, 9##b, 9##c>::value
    > #define BIN4(a, b, c, d) bin<9##a, 9##b, 9##c, 9##d>::value
    >
    > these macros could pass the last test case, but it's not good enough
    > that i have to specify how many numbers i will input.
    >
    > is there any elegant way to resolve this?
    >
    > thanks in advance.


    Iteratore over the binary string backwards, raising by power of 2 and adding
    up.
    Untested code, presuming MyString contains binary string such as "10010010"
    or whatever.
    int value = 0;
    int Multiplier = 1;
    for ( int i = MyString.size() - 1; i >= 0; --i )
    {
    if ( MyString == '1' )
    value += Multiplier;
    Multiplier *= 2;
    }

    At the end value should have the binary value.

    Now, since you have a decimal number you are trying to represent a binary
    number with (not a good idea, you should go with strings or bit map) you
    need to get it to a string. Easy method, use stringstream.
     
    Jim Langston, Sep 12, 2007
    #2
    1. Advertising

  3. Leo jay

    Leo jay Guest

    On Sep 12, 5:42 pm, "Jim Langston" <> wrote:
    >
    > At the end value should have the binary value.
    >
    > Now, since you have a decimal number you are trying to represent a binary
    > number with (not a good idea, you should go with strings or bit map) you
    > need to get it to a string. Easy method, use stringstream.


    thanks for your reply, i know parsing string is a good idea.

    but i want to do it with templates at compile time.
    the best way to learn something is to use it often, isn't it? ;)
     
    Leo jay, Sep 12, 2007
    #3
  4. Leo jay

    Kai-Uwe Bux Guest

    Leo jay wrote:

    > i'd like to implement a class template to convert binary numbers to
    > decimal at compile time.
    > and my test cases are:
    >
    > BOOST_STATIC_ASSERT((bin<1111,1111,1111,1111>::value == 65535));
    > BOOST_STATIC_ASSERT((bin<1111>::value == 15));
    > BOOST_STATIC_ASSERT((bin<0>::value == 0));
    > BOOST_STATIC_ASSERT((bin<1010, 0011>::value == 163));
    >
    > you can find my implementation at:
    > http://pastebin.org/2271
    >
    > the first three cases were ok, but the last one failed, because,
    > compiler will parse 0011
    > as a octal number 9, instead of decimal number 11 because of the
    > leading 0s.
    >
    > to resolve this, i defined 4 macros:
    >
    > #define BIN1(a) bin<9##a>::value
    > #define BIN2(a, b) bin<9##a, 9##b>::value
    > #define BIN3(a, b, c) bin<9##a, 9##b, 9##c>::value
    > #define BIN4(a, b, c, d) bin<9##a, 9##b, 9##c, 9##d>::value
    >
    > these macros could pass the last test case, but it's not good enough
    > that i have to specify how many numbers i will input.
    >
    > is there any elegant way to resolve this?



    Not really elegant, but straight forward and without macros:

    #include <boost/static_assert.hpp>

    template < unsigned int n >
    struct bin_one;

    template <>
    struct bin_one< (unsigned int)(-1) > {

    static unsigned int const value = 0;

    };

    template <>
    struct bin_one<0000> {

    static unsigned int const value = 0;

    };

    template <>
    struct bin_one<0001> {

    static unsigned int const value = 1;

    };

    template <>
    struct bin_one<0010> {

    static unsigned int const value = 2;

    };

    template <>
    struct bin_one<0011> {

    static unsigned int const value = 3;

    };

    template <>
    struct bin_one<0100> {

    static unsigned int const value = 4;

    };

    template <>
    struct bin_one<0101> {

    static unsigned int const value = 5;

    };

    template <>
    struct bin_one<0110> {

    static unsigned int const value = 6;

    };

    template <>
    struct bin_one<0111> {

    static unsigned int const value = 7;

    };


    template <>
    struct bin_one<1000> {

    static unsigned int const value = 8;

    };

    template <>
    struct bin_one<1001> {

    static unsigned int const value = 9;

    };

    template <>
    struct bin_one<1010> {

    static unsigned int const value = 10;

    };

    template <>
    struct bin_one<1011> {

    static unsigned int const value = 11;

    };

    template <>
    struct bin_one<1100> {

    static unsigned int const value = 12;

    };

    template <>
    struct bin_one<1101> {

    static unsigned int const value = 13;

    };

    template <>
    struct bin_one<1111> {

    static unsigned int const value = 15;

    };

    template < unsigned int a, unsigned int b >
    struct bin_two {

    static unsigned int const value =
    bin_one<a>::value * 16 + bin_one<b>::value;

    };

    template < unsigned int a, unsigned int b, unsigned int c >
    struct bin_three {

    static unsigned int const value =
    bin_two<a,b>::value * 16 + bin_one<c>::value;

    };

    template < unsigned int a, unsigned int b, unsigned int c, unsigned int d >
    struct bin_four {

    static unsigned int const value =
    bin_three<a,b,c>::value * 16 + bin_one<d>::value;

    };



    template < unsigned int a,
    unsigned int b = (unsigned int)(-1),
    unsigned int c = (unsigned int)(-1),
    unsigned int d = (unsigned int)(-1) >
    struct bin {

    static unsigned int const value =
    ( b == (unsigned int)(-1) ? bin_one<a>::value : 0 )
    +
    ( b != (unsigned int)(-1) && c == (unsigned int)(-1) ?
    bin_two<a,b>::value : 0 )
    +
    ( c != (unsigned int)(-1) && d == (unsigned int)(-1) ?
    bin_three<a,b,c>::value : 0 )
    +
    ( d != (unsigned int)(-1) ? bin_four<a,b,c,d>::value : 0 );

    };

    int main ( void ) {
    BOOST_STATIC_ASSERT((bin<1111,1111,1111,1111>::value == 65535));
    BOOST_STATIC_ASSERT((bin<1111>::value == 15));
    BOOST_STATIC_ASSERT((bin<0>::value == 0));
    BOOST_STATIC_ASSERT((bin<1010, 0011>::value == 163));
    }


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Sep 12, 2007
    #4
  5. Leo jay

    Greg Comeau Guest

    In article <>,
    Leo jay <> wrote:
    >i'd like to implement a class template to convert binary numbers to
    >decimal at compile time....


    This may not be exactly what you're looking for:
    http://www.comeaucomputing.com/techtalk/#binaryliteral
    but perhaps can give you some ideas.
    --
    Greg Comeau / 4.3.9 with C++0xisms now in beta!
    Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
    World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
    Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
     
    Greg Comeau, Sep 12, 2007
    #5
  6. Leo jay

    Old Wolf Guest

    On Sep 12, 10:08 pm, Kai-Uwe Bux <> wrote:
    > template < unsigned int a,
    > unsigned int b = (unsigned int)(-1),
    > unsigned int c = (unsigned int)(-1),
    > unsigned int d = (unsigned int)(-1) >
    > struct bin {
    >
    > static unsigned int const value =
    > ( b == (unsigned int)(-1) ? bin_one<a>::value : 0 )
    > +
    > ( b != (unsigned int)(-1) && c == (unsigned int)(-1) ?
    > bin_two<a,b>::value : 0 )
    > +
    > ( c != (unsigned int)(-1) && d == (unsigned int)(-1) ?
    > bin_three<a,b,c>::value : 0 )
    > +
    > ( d != (unsigned int)(-1) ? bin_four<a,b,c,d>::value : 0 );
    > };


    None of those casts is required. -1 will be
    converted to unsigned int when used as argument
    of a binary operator where the other argument is
    unsigned int.
     
    Old Wolf, Sep 12, 2007
    #6
  7. Leo jay

    Kai-Uwe Bux Guest

    Old Wolf wrote:

    > On Sep 12, 10:08 pm, Kai-Uwe Bux <> wrote:
    >> template < unsigned int a,
    >> unsigned int b = (unsigned int)(-1),
    >> unsigned int c = (unsigned int)(-1),
    >> unsigned int d = (unsigned int)(-1) >
    >> struct bin {
    >>
    >> static unsigned int const value =
    >> ( b == (unsigned int)(-1) ? bin_one<a>::value : 0 )
    >> +
    >> ( b != (unsigned int)(-1) && c == (unsigned int)(-1) ?
    >> bin_two<a,b>::value : 0 )
    >> +
    >> ( c != (unsigned int)(-1) && d == (unsigned int)(-1) ?
    >> bin_three<a,b,c>::value : 0 )
    >> +
    >> ( d != (unsigned int)(-1) ? bin_four<a,b,c,d>::value : 0 );
    >> };

    >
    > None of those casts is required. -1 will be
    > converted to unsigned int when used as argument
    > of a binary operator where the other argument is
    > unsigned int.


    True, I just wanted to make the compiler shut up about comparisons between
    signed and unsigned types. It did put out tons of warnings.


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Sep 13, 2007
    #7
  8. Leo jay

    Leo jay Guest

    On Sep 12, 6:08 pm, Kai-Uwe Bux <> wrote:
    > Not really elegant, but straight forward and without macros:
    >
    > #include <boost/static_assert.hpp>
    >
    > template < unsigned int n >
    > struct bin_one;
    >
    > template <>
    > struct bin_one< (unsigned int)(-1) > {
    >
    > static unsigned int const value = 0;
    >
    > };
    >
    > template <>
    > struct bin_one<0000> {
    >
    > static unsigned int const value = 0;
    >
    > };
    >


    wow, that's a good idea.
    my new version is:
    http://pastebin.org/2329

    any more ideas?
    thanks.
     
    Leo jay, Sep 13, 2007
    #8
  9. Leo jay

    Kai-Uwe Bux Guest

    Leo jay wrote:

    > On Sep 12, 6:08 pm, Kai-Uwe Bux <> wrote:
    >> Not really elegant, but straight forward and without macros:
    >>
    >> #include <boost/static_assert.hpp>
    >>
    >> template < unsigned int n >
    >> struct bin_one;
    >>
    >> template <>
    >> struct bin_one< (unsigned int)(-1) > {
    >>
    >> static unsigned int const value = 0;
    >>
    >> };
    >>
    >> template <>
    >> struct bin_one<0000> {
    >>
    >> static unsigned int const value = 0;
    >>
    >> };
    >>

    >
    > wow, that's a good idea.
    > my new version is:
    > http://pastebin.org/2329


    Well, I changed it a bit and added that stuff to my code base. Here is the
    version I finally settled for:


    namespace DO_NOT_USE {

    template < unsigned long n >
    struct bin_one;

    template <>
    struct bin_one< 65536 > {

    static unsigned long const value = 0;

    };

    template <>
    struct bin_one<0000> {

    static unsigned long const value = 0;

    };

    template <>
    struct bin_one<0001> {

    static unsigned long const value = 1;

    };

    template <>
    struct bin_one<0010> {

    static unsigned long const value = 2;

    };

    template <>
    struct bin_one<10> {

    static unsigned long const value = 2;

    };

    template <>
    struct bin_one<0011> {

    static unsigned long const value = 3;

    };

    template <>
    struct bin_one<11> {

    static unsigned long const value = 3;

    };

    template <>
    struct bin_one<0100> {

    static unsigned long const value = 4;

    };

    template <>
    struct bin_one<100> {

    static unsigned long const value = 4;

    };

    template <>
    struct bin_one<0101> {

    static unsigned long const value = 5;

    };

    template <>
    struct bin_one<101> {

    static unsigned long const value = 5;

    };

    template <>
    struct bin_one<0110> {

    static unsigned long const value = 6;

    };

    template <>
    struct bin_one<110> {

    static unsigned long const value = 6;

    };

    template <>
    struct bin_one<0111> {

    static unsigned long const value = 7;

    };

    template <>
    struct bin_one<111> {

    static unsigned long const value = 7;

    };

    template <>
    struct bin_one<1000> {

    static unsigned long const value = 8;

    };

    template <>
    struct bin_one<1001> {

    static unsigned long const value = 9;

    };

    template <>
    struct bin_one<1010> {

    static unsigned long const value = 10;

    };

    template <>
    struct bin_one<1011> {

    static unsigned long const value = 11;

    };

    template <>
    struct bin_one<1100> {

    static unsigned long const value = 12;

    };

    template <>
    struct bin_one<1101> {

    static unsigned long const value = 13;

    };

    template <>
    struct bin_one<1111> {

    static unsigned long const value = 15;

    };

    template < unsigned long a, unsigned long b >
    struct bin_two {

    static unsigned long const value =
    bin_one<a>::value * 16 + bin_one<b>::value;

    };

    template
    < unsigned long a, unsigned long b, unsigned long c, unsigned long d >
    struct bin_four {

    static unsigned long const value =
    bin_two<a,b>::value * 256 + bin_two<c,d>::value;

    };

    template
    < unsigned long a, unsigned long b, unsigned long c, unsigned long d,
    unsigned long e, unsigned long f, unsigned long g, unsigned long h >
    struct bin_eight {

    static unsigned long const value =
    bin_four<a,b,c,d>::value * 65536 + bin_four<e,f,g,h>::value;

    };

    } // namespace DO_NOT_USE


    template
    < unsigned long a,
    unsigned long b = 65536,
    unsigned long c = 65536,
    unsigned long d = 65536,
    unsigned long e = 65536,
    unsigned long f = 65536,
    unsigned long g = 65536,
    unsigned long h = 65536 >
    class binary_literal {

    static unsigned long const mask = 65536;

    public:

    static unsigned long const value =
    DO_NOT_USE::bin_eight<a,b,c,d,e,f,g,h>::value >>
    (((b&mask)+(c&mask)+(d&mask)+(e&mask)+(f&mask)+(g&mask)+(h&mask))/16384);

    };



    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Sep 13, 2007
    #9
  10. Leo jay

    Barry Guest

    Leo jay wrote:
    > i'd like to implement a class template to convert binary numbers to
    > decimal at compile time.
    > and my test cases are:
    >
    > BOOST_STATIC_ASSERT((bin<1111,1111,1111,1111>::value == 65535));
    > BOOST_STATIC_ASSERT((bin<1111>::value == 15));
    > BOOST_STATIC_ASSERT((bin<0>::value == 0));
    > BOOST_STATIC_ASSERT((bin<1010, 0011>::value == 163));
    >
    > you can find my implementation at:
    > http://pastebin.org/2271
    >
    > the first three cases were ok, but the last one failed, because,
    > compiler will parse 0011
    > as a octal number 9, instead of decimal number 11 because of the
    > leading 0s.
    >
    > to resolve this, i defined 4 macros:
    >
    > #define BIN1(a) bin<9##a>::value
    > #define BIN2(a, b) bin<9##a, 9##b>::value
    > #define BIN3(a, b, c) bin<9##a, 9##b, 9##c>::value
    > #define BIN4(a, b, c, d) bin<9##a, 9##b, 9##c, 9##d>::value
    >
    > these macros could pass the last test case, but it's not good enough
    > that i have to specify how many numbers i will input.
    >
    > is there any elegant way to resolve this?
    >


    combining your implementation and Kai's from else thread

    // specialization for byte starting with 0
    // 0000 and 0001 is no need specialized
    template <>
    struct bin1 <0010>
    {
    static const unsigned int value = 2u;
    };

    template <>
    struct bin1 <0011>
    {
    static const unsigned int value = 3u;
    };

    template <>
    struct bin1 <0100>
    {
    static const unsigned int value = 4u;
    };

    template <>
    struct bin1 <0101>
    {
    static const unsigned int value = 5u;
    };

    template <>
    struct bin1 <0110>
    {
    static const unsigned int value = 6u;
    };

    template <>
    struct bin1 <0111>
    {
    static const unsigned int value = 7u;
    };

    then

    bin<0010, 0001>::value == bin<10, 1>::value

    --
    Thanks
    Barry
     
    Barry, Sep 13, 2007
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. makok
    Replies:
    1
    Views:
    6,908
    Anders Hellerup Madsen
    Feb 23, 2004
  2. Golan
    Replies:
    7
    Views:
    2,152
    Malcolm
    Dec 8, 2003
  3. QQ

    convert a binary into decimal

    QQ, Mar 22, 2006, in forum: C Programming
    Replies:
    4
    Views:
    547
    Barry Schwarz
    Mar 23, 2006
  4. Vitaliy
    Replies:
    1
    Views:
    489
    Peter Otten
    May 29, 2008
  5. valpa
    Replies:
    11
    Views:
    1,554
    Steven D'Aprano
    Mar 24, 2009
Loading...

Share This Page