convert binary to decimal in template at compiler time.

L

Leo jay

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.
 
J

Jim Langston

Leo jay said:
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.
 
L

Leo jay

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? ;)
 
K

Kai-Uwe Bux

Leo said:
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
 
O

Old Wolf

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.
 
K

Kai-Uwe Bux

Old said:
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
 
L

Leo jay

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.
 
K

Kai-Uwe Bux

Leo said:
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
 
B

Barry

Leo said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top