Muszę jak najszybciej przekonwertować liczbę binarną, na przykład unsigned int bin_number = 10101010
na jej dziesiętną reprezentację (tj. 170
)? Jaki jest najlepszy algorytm?Szybki sposób konwertowania liczby binarnej na liczbę dziesiętną
Odpowiedz
Za pomocą szablonów można rozwiązać ten problem pod numerem podczas kompilacji.
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; };
Szablon binarny jest ponownie tworzony z mniejszą num
, aż num
osiągnie zero, a specjalizacja jest stosowany jako warunek zakończenia.
Przykład: std::cout << binary<10101010>::value;
Dla 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;
}
Czy możesz dać mi przykład? – Nick
Korzystając z szablonów, można obliczać wszystko podczas kompilacji, ponieważ są one kompletne. Czy to jednak pomaga OP osiągnąć cokolwiek? – PlasmaHH
-1: Wątpię w to. Jeśli OP miał LOD, który byłby potrzebny, aby użyć metaprogramowania, mógł po prostu zrobić "const double d = 170.0;" Ponieważ jest on pewny, otrzymując liczbę wejściową w czasie wykonywania, więc metaprogramowanie jest zakończone. –
Właściwie jeśli piszesz unsigned int bin_number = 10101010
, to jest interpretowany jako liczbę dziesiętną przez kompilator.
Jeśli chcesz napisać binarne litteral w kodzie źródłowym, należy użyć BOOST_BINARY.Then wystarczy go wydrukować przy użyciu cout
, dziesiętny jest domyślnym ...
unsigned int i = BOOST_BINARY(10101010);
std::cout << i; // This prints 170
Cóż, jeśli to "liczba" jest w rzeczywistości ciągiem pobranym z jakiegoś źródła (odczytanego z pliku lub z użytkownika), który został przekonwertowany na liczbę (myśląc, że jest bardziej odpowiedni dla rzeczywistej liczby), co jest całkiem prawdopodobne, można użyć wartości std::bitset
wykonać konwersję:
#include <bitset>
unsigned int number = std::bitset<32>("10101010").to_ulong();
(oczywiście 32
tutaj jest zdefiniowane w implementacji i może być bardziej odpowiednio napisany jako std::numeric_limits<unsigned int>::digits
).
Ale jeśli jest to naprawdę numer (zmienna integer) w (bardzo) pierwsze miejsce można zrobić:
#include <string>
unsigned int number = std::bitset<32>(std::to_string(bin_number)).to_ulong();
(używając C++ 11: to_string
) Ale to prawdopodobnie nie będzie najbardziej efektywny sposób, ponieważ inni przedstawili bardziej wydajne algorytmy oparte na liczbach. Ale, jak powiedziałem, wątpię, czy rzeczywiście otrzymujesz tę liczbę jako rzeczywistą zmienną całkowitą w pierwszej kolejności, ale raczej odczytaj ją z jakiegoś pliku tekstowego lub od użytkownika.
Dziękuję, to dobra odpowiedź, ale numer nie jest ciągiem, nie mogę używać C++ 11 i poprosiłem o szybkie rozwiązanie! – Nick
@Nick Więc mogę spytać skąd go wziąłeś, oczywiście musisz go skądś pobrać i wątpię, żebyś rzeczywiście przeczytał liczbę binarną, która reprezentuje liczbę zawierającą tylko cyfry 0 i 1, co byłoby śmieciem.To naprawdę tylko ma sens, aby taką liczbę uzyskać z jakiegoś medium tekstowego. Jedynym wyjątkiem jest sytuacja, gdy potrzebujesz stałych binarnych, ale do tego możesz po prostu użyć innej metody (program szablonu gliderkite jest bardzo ładny). Ale w większości przypadków, gdy jest to ciąg znaków, rozwiązanie bitsetowe nie powinno być najwolniejsze (i nie wymaga też C++ 11). –
btw masz mój +1 – Nick
Jeśli znasz liczbę cyfr binarnych, że masz do czynienia z i to zawsze stałą i liczba binarna jest w ciągu znaków (jak byłoby gdyby odczytać z pliku lub stdin) w czasie wykonywania (tj Konwersja czasu kompilacji nie jest możliwa), możesz zastosować następujące podejście:
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);
}
Zakłada to stały ośmioramienny numer binarny.nazywane tak:
std::cout << to_binary("10101010") << std::endl;
Jeśli miał szesnaście numer bitu można nadal używać go:
const char* bin_number = "1010101010101010";
// Deal with 16 bits
std::cout << (to_binary(bin_number) << 8 | to_binary(bin_number + 8)) << std::endl;
Należy pamiętać, że nie istnieje wyraźne granice kontrolne tutaj i jestem powołując się na fakt, że LSB z "1" ma zawsze wartość 1, a "0" zawsze wynosi 0 (więc nie sprawdza poprawności, że jest to wejście binarne).
Oczywiście jest to dość specyficzne i niezbyt elastyczne, ale działa i jestem nie jestem pewien, że dostaniesz znacznie szybciej.
Czy '10101010' pochodzi od użytkownika twojego programu, czy jest to tylko literał w kodzie? –
Czy możesz podać lepszy obraz skąd pochodzi liczba binarna? Czy jest znany podczas kompilacji lub tylko w czasie wykonywania? Czy jest przechowywany w ciągu znaków lub w innej strukturze? Znajomość tego znacznie ułatwi udzielenie odpowiedzi na to pytanie. –
Tak, przepraszam. Zazwyczaj uzyskuję liczbę uruchomień, ale czasami podczas kompilacji. Nadal się uczę. – Nick