2016-03-15 87 views
6

ho bisogno di fare un programma che conta il numero di 1s nella rappresentazione binaria di un numero senza segno, utilizzando una funzione ricorsiva, quindi questo è il mio codice:Numero di 1s in un numero binario

#include <stdio.h> 
#include <stdlib.h> 

int one(unsigned n); 

int main() 
{ 
    unsigned n; 
    printf("n= "); scanf("%u", &n); 
    printf("%d", one(n)); 

    printf("\n"); 
    return 0; 
} 

int one(unsigned n) 
{ 
    if(n==1 || n==0) 
     return n; 
    else 
     return (n&1+one(n>>1)); 
} 

Thing è, il mio codice funziona per il numero 7 per esempio, ma se inserisco il numero 2 verrà stampato che contiene 2. E per 4 restituisce 0, e penso che per tutti gli esponenti di 2 restituisca 0 alla fine. Non riesco a capire perché.

+0

La prima cosa che proverei è ripulire i valori restituiti e così via. Stai restituendo un int firmato, passando in qualcosa di non firmato? Quindi .. idealmente, tieni tutto senza firma quando esegui la manipolazione bit a bit. Puoi farlo in entrambi i modi, ma è più facile sapere con certezza che stai facendo quello che pensi di fare ... se questo ha senso. Come parte di ciò, dovresti stampare un% u su entrambe le linee. Facci sapere se continui ad avere un problema dopo aver ottenuto tutti i tuoi argomenti in unsigned –

+0

Provato e lo stesso risultato. – Nebeski

+0

http://en.cppreference.com/w/c/language/operator_precedence –

risposta

2

Il problema principale è qui:

return (n&1+one(n>>1)); 

L'operatore di addizione + operatore ha una precedenza che il bit-E operatore &. Quindi l'espressione è efficace:

return (n & (1 + one(n >> 1))); 

è necessario aggiungere le parentesi intorno n&1:

return ((n & 1) + one(n >> 1)); 

EDIT:

Come un esercizio di programmazione, questo funziona bene. Nel codice della vita reale, una tabella di ricerca precalcolata è molto più efficiente.

// Assumes CHAR_BITS == 8 

int numbits[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 
        ... 
        4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; 

int count_bits(unsigned n) 
{ 
    int i, count = 0; 
    for (i=0; i<sizeof(n); i++) { 
     count += numbits[(uint8_t)(n & 0xFF)]; 
     n >>= 8; 
    } 
} 
+0

Non sono sicuro delle prestazioni qui, considerando la velocità delle cose * computing * al giorno d'oggi, rispetto alla lentezza degli accessi alla memoria, ma questo potrebbe dipendere dal caching e dal modello di utilizzo, quindi è difficile fare una dichiarazione definitiva qui. In ogni caso, per alternative, si potrebbe voler dare un'occhiata al [Bit Twiddling Hacks] (https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive), che presenta 7 modi di contare il set bit. – Marco13

2

L'operatore & ha una precedenza inferiore alla + operatore, che provoca il calcolo nel else ramo o one per produrre il (logicamente) risultato sbagliato. Basta circondano da parentesi per assicurarsi che sia eseguita per prima e si dovrebbe andare bene:

return (n & 1) + one(n>>1); 
2

In questa linea

return (n&1+one(n>>1)); 

L'operatore + ha una priorità più alta rispetto &. Ma prima devi mascherare l'ultimo bit, quindi aggiungerlo:

return ((n&1) + one(n>>1));