2015-02-08 15 views
7

Utilizzo dell'operatore bit a bit come è possibile verificare se i bit meno significativi di un numero intero sono tutti set o non set.Come posso verificare se tutti i bit sono impostati o tutti i bit no?

Ad esempio if n = 3 Ho solo cura circa 3 bit meno significativi Il test deve restituire true per 0 e 7 e false per tutti gli altri valori tra 0 e 7.

Naturalmente ho potuto fare if x = 0 or x = 7, ma avrei preferisci qualcosa usando operatori bit a bit.

Punti bonus se la tecnica può essere adattata per tenere conto di tutti i bit definiti da una maschera.

Chiarimento:

Se ho voluto mettere alla prova se il bit uno o due è impostato che potevo per if ((x & 1 != 0) && (x & 2 != 0)). Ma potrei fare il "più efficiente" if ((x & 3) != 0).

Sto cercando di trovare un "trucco" come questo per rispondere alla domanda "Tutti i bit di x che corrispondono a questa maschera sono tutti impostati o tutti annullati?"

Il modo più semplice è if ((x & mask) == 0 || (x & mask) == mask). Mi piacerebbe trovare un modo per farlo in una singola prova senza || operatore.

+0

Qual è il caso d'uso? Perché vuoi un metodo del genere –

+0

Mi interessano gli hack di manipolazione dei bit leggendo qui https://graphics.stanford.edu/~seander/bithacks.html e sto cercando di trovare un modo per testare se tutti i bit di un mascherato sono tutti o 1 o tutti 0. È solo curiosità, mi chiedo se può essere fatto. –

+0

diverse risposte commettono l'errore di scrivere '1 << n'. Ciò causa un comportamento indefinito se 'n> = 31' (se sei su un sistema int a 32 bit). Il '1' deve essere castato per essere di tipo unsigned che sia largo almeno quanto il valore che stai testando. –

risposta

10

Utilizzo dell'operatore bit a bit come è possibile verificare se i bit meno significativi di un numero intero sono tutti set o non tutti set.

Per ottenere una maschera per gli ultimi n bit significativi, thats

(1ULL << n) - 1 

Così il semplice test è:

bool test_all_or_none(uint64_t val, uint64_t n) 
{ 
    uint64_t mask = (1ULL << n) - 1; 
    val &= mask; 
    return val == mask || val == 0; 
} 

Se si vuole evitare il ||, avremo trarre vantaggio dall'overflow dei numeri interi. Per i casi desiderati, dopo &, val è 0 o (supponiamo n == 8) 0xff. Quindi val - 1 è o 0xffffffffffffffff o 0xfe. Le cause di errore sono 1 tramite 0xfe, che diventano 0 tramite 0xfd.Così i casi di successo sono chiamata almeno 0xfe, che è mask - 1:

bool test_all_or_none(uint64_t val, uint64_t n) 
{ 
    uint64_t mask = (1ULL << n) - 1; 
    val &= mask; 
    return (val - 1) >= (mask - 1); 
} 

Possiamo anche prova con l'aggiunta di 1 invece di sottrarre 1, che è probabilmente la soluzione migliore (qui quando abbiamo aggiungere uno a val, val & mask dovrebbe diventare sia 0 o 1 per i nostri casi di successo):

bool test_all_or_none(uint64_t val, uint64_t n) 
{ 
    uint64_t mask = (1ULL << n) - 1; 
    return ((val + 1) & mask) <= 1; 
}  

per un arbitrario maschera , il metodo di sottrazione funziona per la stessa ragione che ha funzionato per il caso maschera specifica: il 0 ribalta per essere il più grande valore possibile:

bool test_all_or_none(uint64_t val, uint64_t mask) 
{ 
    return ((val & mask) - 1) >= (mask - 1); 
} 
+0

Non sto cercando un modo per testarli separatamente. Voglio testare entrambi allo stesso tempo. –

+0

@ MathieuPagé È arrivato con uno ancora migliore. – Barry

+0

Bello. Questa risposta alla mia domanda originale dove volevo testare i bit meno significativi. Se non troviamo una versione che funzioni per una maschera arbitraria, accetterò questa risposta. Grazie. –

3

Che ne dici?

int mask = (1<<n)-1; 
if ((x&mask)==mask || (x&mask)==0) { /*do whatever*/ } 

L'unica parte veramente difficile è il calcolo della maschera. In pratica sposta semplicemente un 1 su per ottenere 0b0...0100...0 e quindi sottrae uno per renderlo 0b0...0011...1.

Forse puoi chiarire cosa volevi per il test?

+0

Vorrei testarlo senza usare || operatore. –

+1

@ MathieuPagé usa '|' – ryanpattison

+0

@MattMcNabb; mentre mi ricordavo del primo mandato, era stato escluso dal secondo. Fisso. – imallett

0

per verificare se tutti non sono impostati, non vi resta che mascherare-in solo i bit che si desidera, allora non vi resta che confrontare a zero.

Il divertimento inizia quando si definisce la funzione oposite semplicemente invertendo l'ingresso :)

//Test if the n least significant bits arent set: 
char n_least_arent_set(unsigned int n, unsigned int value){ 
    unsigned int mask = pow(2, n) - 1; // e. g. 2^3 - 1 = b111 
    int masked_value = value & mask; 
    return masked_value == 0; // if all are zero, the mask operation returns a full-zero.  
} 

//test if the n least significant bits are set: 
char n_least_are_set(unsigned int n, unsigned int value){ 
    unsigned int rev_value = ~value; 
    return n_least_arent_set(n, rev_value);  
} 
1

Ecco cosa si voleva fare, in una funzione (non testato, ma si dovrebbe ottenere l'idea). Restituisce 0 se gli ultimi n bit non sono impostati, 1 se sono tutti impostati, -1 altrimenti.

int lastBitsSet(int num, int n){ 
    int mask = (1 << n) - 1; //n 1-s 
    if (!(num & mask)) //we got all 0-s 
     return 0; 
    if (!(~num & mask)) //we got all 1-s 
     return 1; 
    else 
     return -1; 
} 
+0

Hi Mints97, sto cercando un modo per farlo in una singola prova. @Barry ha trovato un modo per farlo nel caso in cui la maschera copra i bit non significativi di significati. –

+0

@ MathieuPagé: sì, ma il suo metodo non distingue tra i casi in cui gli ultimi bit sono tutti impostati o tutti non impostati. – Mints97

+0

Infatti. Era quello che stavo cercando. –

Problemi correlati