I have to convert a binary number like for example unsigned int bin_number = 10101010
into its decimal representation (i.e. 170
) as quickly as possible
Since C++11 (even if C++11 is more limited than C++14 in that regard), function can be constexpr
so avoid necessity of template
to have compile time value.
Here a version C++14 compatible:
constexpr unsigned binary_to_decimal(unsigned num)
{
unsigned res = 0;
while (num)
{
res = 10 * res + num % 10;
num /= 10;
}
return res;
}
And for literals, you can even use binary literals since C++14:
0b1010'1010 // or 0b10101010 without separator
Well, if this "number" is actually a string gotten from some source (read from a file or from a user) that you converted into a number (thinking it to be more appropriate for an actual number), which is quite likely, you can use a std::bitset
to do the conversion:
#include <bitset>
unsigned int number = std::bitset<32>("10101010").to_ulong();
(Of course the 32
here is implementation-defined and might be more appropriately written as std::numeric_limits<unsigned int>::digits
.)
But if it is really a number (integer variable) in the (very) first place you could do:
#include <string>
unsigned int number = std::bitset<32>(std::to_string(bin_number)).to_ulong();
(using C++11's to_string
) But this will probably not be the most efficient way anymore, as others have presented more efficient algorithms based on numbers. But as said, I doubt that you really get this number as an actual integer variable in the very first place, but rather read it from some text file or from the user.
If you know the number of binary digits that you're dealing with and it's always fixed and the binary number comes in a string (as it would if read from a file or stdin) at runtime (i.e. compile time conversion not possible) then you could adopt this approach:
int to_binary( const char* c )
{
return ( ( c[0] & 1 ) ? 0x80 : 0x00 ) |
( ( c[1] & 1 ) ? 0x40 : 0x00 ) |
( ( c[2] & 1 ) ? 0x20 : 0x00 ) |
( ( c[3] & 1 ) ? 0x10 : 0x00 ) |
( ( c[4] & 1 ) ? 0x08 : 0x00 ) |
( ( c[5] & 1 ) ? 0x04 : 0x00 ) |
( ( c[6] & 1 ) ? 0x02 : 0x00 ) |
( ( c[7] & 1 ) ? 0x01 : 0x00 );
}
This assumes an fixed eight digit binary number. called like this:
std::cout << to_binary("10101010") << std::endl;
If you had a sixteen bit number you could still use it:
const char* bin_number = "1010101010101010";
// Deal with 16 bits
std::cout << ( to_binary( bin_number ) << 8 | to_binary( bin_number + 8 ) ) << std::endl;
Note that there is clearly no bounds checking here and I'm relying on the fact that the LSB of '1' is always 1 and '0' is always 0 (so not validating that it's actually a binary input.)
Naturally, it's pretty specific and not very flexible, but it does the job and I'm not sure that you'd get much faster.
Actually if you write unsigned int bin_number = 10101010
, this is interpreted as a decimal number by the compiler.
If you want to write a binary literal in your source code, you should use BOOST_BINARY. Then, you just need to print it using cout
, decimal is the default...
unsigned int i = BOOST_BINARY(10101010);
std::cout << i; // This prints 170
Using templates you can solve this problem at compile-time.
template<unsigned long num>
struct binary
{
static unsigned const value =
binary<num/10>::value << 1 | num % 10;
};
// Specialization for zero
template<>
struct binary<0>
{ static unsigned const value = 0; };
The binary template is instantiated again with a smaller num
, until num
reaches zero and the specialization is used as a termination condition.
Example: std::cout << binary<10101010>::value;
For run-time problem:
unsigned binary_to_decimal(unsigned num)
{
unsigned res = 0;
for(int i = 0; num > 0; ++i)
{
if((num % 10) == 1)
res += (1 << i);
num /= 10;
}
return res;
}