modo più efficace per estrarre flag di bit
Domanda
Ho questi possibili flag di bit.
1, 2, 4, 8, 16, 64, 128, 256, 512, 2048, 4096, 16384, 32768, 65536
Quindi, ogni numero è come una vera e propria dichiarazione falsa / sul lato server. Quindi, se i primi 3 elementi, e solo i primi 3 articoli sono contrassegnati "vero" sul lato server, il servizio di web restituirà un 7. Se tutti i 14 articoli di cui sopra sono vere, mi sarebbe ancora ottenere un numero singolo di ritorno dal servizio web che è è la somma di tutti quei numeri.
Qual è il modo migliore per gestire il numero di torno per scoprire quali elementi sono contrassegnati come "vera"?
Soluzione
if (7 & 1) { // if bit 1 is set in returned number (7)
}
Altri suggerimenti
Usa un operatore di mascheramento di bit. Nel linguaggio C:
X & 8
è vero, se è impostato il "8" bit s.
È possibile enumerare le maschere di bit, e contare quanti sono impostati.
Se è davvero il caso che l'intera parola contiene bit, e si desidera semplicemente calcolare quanti bit sono impostati, si vuole in sostanza un "conteggio della popolazione". l'assoluto modo più veloce per ottenere un conteggio della popolazione è quello di eseguire un "POPCNT" nativo di solito disponibili in set di istruzioni della macchina.
Se non si cura di spazio, è possibile impostare un array countedbits [...] indicizzato dal valore con i conteggi bit precalcolate. Poi un singolo accesso alla memoria calcola il valore del bit.
Spesso usato è semplicemente "codice bit giocherellando" che calcola bit conta :
(il metodo di Kernigan):
unsigned int v; // count the number of bits set in v
unsigned int c; // c accumulates the total bits set in v
for (c = 0; v; c++)
{
v &= v - 1; // clear the least significant bit set
}
(parallelo bit summming, 32 bit)
v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
Se non avete visto gli hack po mani in prima, siete dentro per un ossequio.
PHP, essere divertente, può fare cose divertenti con un po 'di questa aritmetica.
Il pensiero la domanda è vecchia potrebbe aiutare qualcun altro. Sto mettendo i numeri in binario come la sua più chiara per capire. Il codice non era stato testato, ma spero la logica è chiara. Il codice è PHP specifico.
define('FLAG_A', 0b10000000000000);
define('FLAG_B', 0b01000000000000);
define('FLAG_C', 0b00100000000000);
define('FLAG_D', 0b00010000000000);
define('FLAG_E', 0b00001000000000);
define('FLAG_F', 0b00000100000000);
define('FLAG_G', 0b00000010000000);
define('FLAG_H', 0b00000001000000);
define('FLAG_I', 0b00000000100000);
define('FLAG_J', 0b00000000010000);
define('FLAG_K', 0b00000000001000);
define('FLAG_L', 0b00000000000100);
define('FLAG_M', 0b00000000000010);
define('FLAG_N', 0b00000000000001);
function isFlagSet($Flag,$Setting,$All=false){
$setFlags = $Flag & $Setting;
if($setFlags and !$All) // at least one of the flags passed is set
return true;
else if($All and ($setFlags == $Flag)) // to check that all flags are set
return true;
else
return false;
}
Utilizzo:
if(isFlagSet(FLAG_A,someSettingsVariable)) // eg: someSettingsVariable = 0b01100000000010
if(isFlagSet(FLAG_A | FLAG_F | FLAG_L,someSettingsVariable)) // to check if atleast one flag is set
if(isFlagSet(FLAG_A | FLAG_J | FLAG_M | FLAG_D,someSettingsVariable, TRUE)) // to check if all flags are set
Un modo sarebbe ciclo tra il proprio numero, sinistra-shifting (cioè dividere per 2) e confrontare il primo bit con 1 usando l'& operando.
Poiché non v'è alcuna risposta definitiva con il codice PHP, aggiungo questo esempio di lavoro:
// returns array of numbers, so for 7 returns array(1,2,4), etc..
function get_bits($decimal) {
$scan = 1;
$result = array();
while ($decimal >= $scan){
if ($decimal & $scan) $result[] = $scan;
$scan<<=1;
}
return $result;
}