Мне нужно как можно быстрее преобразовать двоичное число, например, unsigned int bin_number = 10101010
в его десятичное представление (т.е. 170
)? Каков наилучший алгоритм?
Быстрый способ преобразования двоичного числа в десятичное число
Ответ 1
Используя шаблоны, вы можете решить эту проблему во время компиляции.
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; };
Двоичный шаблон создается снова с меньшим num
, пока num
не достигнет нуля, и специализация будет использоваться в качестве условия завершения.
Пример: std::cout << binary<10101010>::value;
Для проблемы времени выполнения:
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;
}
Ответ 2
Ну, если это "число" на самом деле является строкой, полученной из некоторого источника (считанного из файла или из пользователя), который вы преобразовали в число (считая его более подходящим для фактического числа), что вполне Вероятно, вы можете использовать std::bitset
для преобразования:
#include <bitset>
unsigned int number = std::bitset<32>("10101010").to_ulong();
(Конечно, 32
здесь определяется реализацией и может быть более правильно написан как std::numeric_limits<unsigned int>::digits
.)
Но если это действительно число (целочисленная переменная) в (очень) первом месте, которое вы могли бы сделать:
#include <string>
unsigned int number = std::bitset<32>(std::to_string(bin_number)).to_ulong();
(используя С++ 11 to_string
). Но это, вероятно, не будет наиболее эффективным способом, поскольку другие представили более эффективные алгоритмы, основанные на числах. Но, как сказано, я сомневаюсь, что вы действительно получите это число как фактическую целочисленную переменную в самом первом месте, а скорее прочитайте ее из какого-либо текстового файла или из пользователя.
Ответ 3
На самом деле, если вы пишете unsigned int bin_number = 10101010
, это интерпретируется компилятором как десятичное число.
Если вы хотите написать двоичный литерал в своем исходном коде, вы должны использовать BOOST_BINARY
. Затем вам просто нужно распечатать его с помощью cout
, по умолчанию используется десятичная дробь...
unsigned int i = BOOST_BINARY(10101010);
std::cout << i; // This prints 170
Ответ 4
Поскольку С++ 11 (даже если С++ 11 в этом отношении более ограничен, чем С++ 14), функция может быть constexpr
поэтому избегайте необходимости в template
иметь значение времени компиляции.
Здесь версия С++ 14 совместима:
constexpr unsigned binary_to_decimal(unsigned num)
{
unsigned res = 0;
while (num)
{
res = 10 * res + num % 10;
num /= 10;
}
return res;
}
А для литералов вы можете даже использовать двоичные литералы начиная с С++ 14:
0b1010'1010 // or 0b10101010 without separator
Ответ 5
Если вам известно количество двоичных цифр, с которыми вы имеете дело, и оно всегда исправлено, и двоичное число приходит в строке (как если бы оно было бы прочитано из файла или stdin) во время выполнения (т.е. невозможно преобразовать время компиляции), тогда вы можете применить этот подход:
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 );
}
Это предполагает фиксированное восьмизначное двоичное число. называется так:
std::cout << to_binary("10101010") << std::endl;
Если у вас было шестнадцатибитное число, вы все равно можете его использовать:
const char* bin_number = "1010101010101010";
// Deal with 16 bits
std::cout << ( to_binary( bin_number ) << 8 | to_binary( bin_number + 8 ) ) << std::endl;
Обратите внимание, что здесь явно нет ограничений, и я полагаюсь на то, что LSB "1" всегда 1, а "0" всегда 0 (поэтому не проверяем, что он фактически является двоичным вводом.)
Естественно, он довольно конкретный и не очень гибкий, но он выполняет эту работу, и я не уверен, что вы получите гораздо быстрее.
Ответ 6
Во время компиляции вам даже не нужен шаблон. Вы можете просто использовать нотацию 0b
.
#include <iostream>
int main(){
int i = 0b10101010;
std::cout << i << std::endl;
return 0;
}