php - poner - La forma más eficiente de extraer banderas de bits
php<=> (5)
Como no hay una respuesta definitiva con el código php, agrego este ejemplo de trabajo:
// 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;
}
Tengo estos posibles indicadores de bits.
1, 2, 4, 8, 16, 64, 128, 256, 512, 2048, 4096, 16384, 32768, 65536
Entonces cada número es como una declaración de verdadero / falso en el lado del servidor. Entonces, si los primeros 3 ítems, y solo los primeros 3 ítems están marcados como "verdaderos" en el lado del servidor, el servicio web devolverá un 7. O si los 14 ítems anteriores son verdaderos, aún así obtendría un solo número del el servicio web que es la suma de todos esos números.
¿Cuál es la mejor manera de manejar el número que recibo para averiguar qué elementos están marcados como "verdaderos"?
Pensé que la pregunta es vieja podría ayudar a alguien más. Estoy poniendo los números en binario como es más claro de entender. El código no se había probado, pero espero que la lógica sea clara. El código es específico de PHP.
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;
}
Uso:
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
Una forma sería recorrer su número, desplazarlo a la izquierda (es decir, dividir por 2) y comparar el primer bit con 1 usando el operando.
Use un operador de enmascaramiento de bits. En el lenguaje C:
X & 8
es verdadero, si el bit "8" está configurado.
Puede enumerar las máscaras de bits y contar cuántas se establecen.
Si realmente es el caso de que toda la palabra contiene bits, y usted simplemente quiere calcular cuántos bits se establecen, quiere en esencia un "recuento de población". La forma más rápida y sencilla de obtener un recuento de población es ejecutar un "popcnt" nativo generalmente disponible en el conjunto de instrucciones de su máquina.
Si no le importa el espacio, puede configurar una matriz contados [...] indexados por su valor con recuentos de bits precalculados. Luego, un solo acceso a la memoria computa su cuenta de bits.
A menudo se usa simplemente el "código de intercambio de bits" que calcula el conteo de bits:
(Método de 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
}
(suma de bit paralelo, 32 bits)
v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
Si no has visto el truco antes, te espera una sorpresa.
PHP, siendo gracioso, puede hacer cosas graciosas con algo de esta aritmética.
if (7 & 1) { // if bit 1 is set in returned number (7)
}