2012-06-08 4 views
9

Мне нужно как можно быстрее преобразовать двоичное число, например, unsigned int bin_number = 10101010 в его десятичное представление (т. Е. 170)? Каков наилучший алгоритм?Быстрый способ преобразования двоичного числа в десятичное число

+1

Есть ли '10101010' от пользователя вашей программы или это просто буквальный код? –

+0

Можете ли вы дать лучшее представление о том, откуда берется двоичный номер? Известно ли это во время компиляции или только во время выполнения? Сохраняется ли она в строке или какой-либо другой структуре? Знание этого позволит значительно облегчить ответ на этот вопрос. –

+0

Да, извините. Обычно я получаю число run-time, но иногда во время компиляции. Я все еще учусь. – Nick

ответ

10

Использование шаблонов Вы можете решить эту проблему на 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; }; 

Двоичный шаблон снова экземпляр с меньшим 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; 
} 
+0

Можете ли вы привести мне пример? – Nick

+4

С помощью шаблонов вы можете вычислить что угодно во время компиляции, так как они завершены. Оказывает ли это, однако, помощь, чтобы сделать что-нибудь? – PlasmaHH

+1

-1: Я сомневаюсь. Если бы у OP был ICE, который ему понадобился для использования метапрограммирования, он мог бы просто выполнить 'const double d = 170.0;' Как он уверен, что он получает входящий номер во время выполнения, поэтому метапрограммирование отсутствует. –

3

На самом деле, если вы пишете unsigned int bin_number = 10101010, это интерпретируется как десятичное число компилятором.

Если вы хотите, чтобы написать двоичный litteral в исходном коде, вы должны использовать BOOST_BINARY.Then вам просто нужно напечатать его с помощью cout, десятичной по умолчанию ...

unsigned int i = BOOST_BINARY(10101010); 
std::cout << i; // This prints 170 
+0

Что такое BOOST_BINARY? – Nick

+0

Некоторые компиляторы также поддерживают префикс «0b» ('i = 0b10101010'), но с повышением вы обеспечиваете переносимость. – Aurel

+0

Boost - это библиотека C++, посмотрите http://www.boost.org/. – Aurel

7

Ну, если это «число» на самом деле является строкой, полученной из некоторого источника (считанного из файла или из пользователя), который вы преобразовали в число (считая его более подходящим для фактического числа), что вполне вероятно, вы можете использовать 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(); 

(с использованием C++ 11's to_string) Но это, вероятно, не будет наиболее эффективным способом, поскольку другие представили более эффективные алгоритмы, основанные на числах. Но, как сказано, я сомневаюсь, что вы действительно получите это число как фактическую целочисленную переменную в самом первом месте, а скорее прочитайте ее из какого-либо текстового файла или из пользователя.

+0

Спасибо, это хороший ответ, но число не является строкой, я не могу использовать C++ 11, и я попросил быстрое решение! – Nick

+0

@Nick Итак, могу ли я спросить, откуда вы его взяли, вы, очевидно, должны его получить откуда-то, и я сомневаюсь, что вы действительно прочитали двоичное число, которое представляет число, содержащее только 0 и 1, что было бы мусором.На самом деле имеет смысл только получить такой номер с некоторой текстовой среды. Единственное исключение - когда вам нужны бинарные константы, но для этого вы можете просто использовать другой метод (программа шаблонов gliderkite очень хороша). Но в большинстве случаев, когда он приходит как строка, решение битов не должно быть самым медленным (и ему тоже не нужен C++ 11). –

+0

btw у вас есть мой +1 – Nick

0

Если вы знаете, число двоичных цифр, которые вы имеете дело с и это всегда фиксированной и двоичное число приходит в строке (как это было бы, если чтение из файла или стандартного ввода) во время выполнения (т.е. невозможность преобразования времени компиляции), вы можете принять такой подход:

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 (поэтому не проверяем, что это фактически двоичный вход.)

Естественно, это довольно конкретный и не очень гибкий, но он выполняет эту работу, и я не уверен, что вы получите гораздо быстрее.

Смежные вопросы