468,785 Members | 1,672 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,785 developers. It's quick & easy.

convert binary to decimal in template at compiler time.

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>::val ue == 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.

Sep 12 '07 #1
9 3149
"Leo jay" <Py***********@gmail.comwrote in message
news:11**********************@w3g2000hsg.googlegro ups.com...
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>::val ue == 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[i] == '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.

Sep 12 '07 #2
On Sep 12, 5:42 pm, "Jim Langston" <tazmas...@rocketmail.comwrote:
>
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? ;)

Sep 12 '07 #3
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>::val ue == 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>::val ue == 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
Sep 12 '07 #4
In article <11**********************@w3g2000hsg.googlegroups. com>,
Leo jay <Py***********@gmail.comwrote:
>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?
Sep 12 '07 #5
On Sep 12, 10:08 pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:
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.
Sep 12 '07 #6
Old Wolf wrote:
On Sep 12, 10:08 pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:
>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
Sep 12 '07 #7
On Sep 12, 6:08 pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:
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.

Sep 13 '07 #8
Leo jay wrote:
On Sep 12, 6:08 pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:
>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
Sep 13 '07 #9
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>::val ue == 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
Sep 13 '07 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by ferran | last post: by
5 posts views Thread by Ruben Campos | last post: by
4 posts views Thread by jaijai_kumar | last post: by
5 posts views Thread by Ray | last post: by
4 posts views Thread by QQ | last post: by
7 posts views Thread by elliotng.ee | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
2 posts views Thread by Marin | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.