2012-06-08 21 views
9

Devo convertire un numero binario come ad esempio unsigned int bin_number = 10101010 nella sua rappresentazione decimale (ad esempio 170) il più rapidamente possibile? Qual è il miglior algoritmo?Modo rapido per convertire un numero binario in un numero decimale

+1

Il valore "10101010" proviene dall'utente del programma o è solo un codice letterale? –

+0

Puoi dare un quadro migliore di dove proviene il numero binario? È noto in fase di compilazione o solo in fase di esecuzione? È memorizzato in una stringa o in un'altra struttura? Sapere questo renderà la risposta alla domanda molto più facile. –

+0

Sì, mi dispiace. Di solito ottengo il numero di run-time, ma a volte in fase di compilazione. Sto ancora imparando. – Nick

risposta

10

Utilizzando i modelli è possibile risolvere questo problema allo in fase di compilazione.

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; }; 

Il modello binario è un'istanza di nuovo con un più piccolo num, fino num raggiunge zero e la specializzazione viene utilizzato come condizione di terminazione.

Esempio: std::cout << binary<10101010>::value;

Per runtime problema:

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

Puoi farmi un esempio? – Nick

+4

Utilizzando i modelli è possibile calcolare qualsiasi cosa al momento della compilazione, poiché sono completi. Questo comunque aiuta l'OP a fare qualcosa? – PlasmaHH

+1

-1: ne dubito. Se OP avesse un ICE, di cui avrebbe avuto bisogno per usare la metaprogrammazione, poteva semplicemente fare 'const double d = 170.0;' Poiché è sicuro che ottiene il numero in entrata in fase di esecuzione, quindi la metaprogrammazione è fuori. –

3

In realtà se si scrive unsigned int bin_number = 10101010, questo viene interpretato come un numero decimale dal compilatore.

Se si vuole scrivere un letterale binario nel codice sorgente, si dovrebbe usare BOOST_BINARY.Then basta stamparlo utilizzando cout, decimale è il default ...

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

Che cos'è BOOST_BINARY? – Nick

+0

Alcuni compilatori supportano anche il prefisso "0b" ('i = 0b10101010'), ma con boost si garantisce la portabilità. – Aurel

+0

Boost è una libreria C++, dai un'occhiata a http://www.boost.org/. – Aurel

7

Beh, se questo "number" è in realtà una stringa ottenuta da una fonte (letta da un file o da un utente) che è stata convertita in un numero (pensando che sia più appropriato per un numero reale), che è abbastanza probabile, è possibile utilizzare uno std::bitset fare la conversione:

#include <bitset> 

unsigned int number = std::bitset<32>("10101010").to_ulong(); 

(Naturalmente il 32 qui è definito dall'implementazione e potrebbe essere più appropriatamente scritto come std::numeric_limits<unsigned int>::digits.)

Ma se è veramente un numero (variabile intera) nel (molto) primo luogo si potrebbe fare:

#include <string> 

unsigned int number = std::bitset<32>(std::to_string(bin_number)).to_ulong(); 

(utilizzando C++ 11's to_string) Ma questo probabilmente non sarà più il modo più efficiente, in quanto altri hanno presentato algoritmi più efficienti basati sui numeri. Ma come detto, dubito che tu abbia davvero ottenuto questo numero come una variabile intera vera in primo luogo, ma piuttosto lo leggi da qualche file di testo o dall'utente.

+0

Grazie, questa è una buona risposta, ma il numero non è una stringa, non posso usare C++ 11 e ho chiesto una soluzione veloce! – Nick

+0

@Nick Quindi posso chiederti da dove l'hai preso, ovviamente devi averlo da qualche parte e dubito che tu abbia effettivamente letto un numero binario, che rappresenta un numero che contiene solo 0 e 1, sarebbe spazzatura.In primo luogo, ha senso solo ottenere un numero tale da un supporto testuale. L'unica eccezione è quando hai bisogno di costanti binarie, ma per questo puoi semplicemente usare un altro metodo (il programma template di gliderkite è molto carino). Ma per la maggior parte dei casi quando si tratta di una stringa, la soluzione bitset non dovrebbe essere la più lenta (e nemmeno C++ 11). –

+0

btw hai il mio +1 – Nick

0

Se si conosce il numero di cifre binarie che hai a che fare con e è sempre fisso e il numero binario è disponibile in una stringa (come sarebbe se letta da un file o stdin) in fase di esecuzione (ad esempio non è possibile la conversione del tempo di compilazione) è possibile adottare questo approccio:

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); 
} 

Questo presuppone un numero binario a otto cifre fisso.chiamato in questo modo:

std::cout << to_binary("10101010") << std::endl; 

Se si ha un numero di bit sedici si potrebbe ancora usarlo:

const char* bin_number = "1010101010101010"; 

// Deal with 16 bits 
std::cout << (to_binary(bin_number) << 8 | to_binary(bin_number + 8)) << std::endl; 

Si noti che non v'è chiaramente no controllo dei limiti qui e sto contando sul fatto che il LSB di "1" è sempre 1 e "0" è sempre 0 (quindi non convalidare che sia effettivamente un ingresso binario)

Naturalmente, è piuttosto specifico e non molto flessibile, ma fa il lavoro e io sono non sono sicuro che saresti diventato molto più veloce.

Problemi correlati