Bitvisa

Från Wiki.linux.se
Version från den 17 augusti 2024 kl. 05.57 av Admin (diskussion | bidrag) (→‎Se också)
(skillnad) ← Äldre version | Nuvarande version (skillnad) | Nyare version → (skillnad)
Hoppa till navigering Hoppa till sök

Bitvisa Operatorer

Bitvisa operatorer tillåter utvärdering och manipulation av specifika bitar inom ett heltal.

Bitvisa operatorer

Exempel Namn Resultat
$a & $b Och Bitar som är satta i både $a och $b är satta.
$b Eller (inklusivt eller) Bitar som är satta i antingen $a eller $b är satta.
$a ^ $b Xor (exklusivt eller) Bitar som är satta i antingen $a eller $b men inte båda är satta.
~$a Inte Bitar som är satta i $a är inte satta, och vice versa.
$a << $b Skifta vänster Skiftar bitarna i $a $b steg till vänster (varje steg betyder "multiplicera med två")
$a >> $b Skifta höger Skiftar bitarna i $a $b steg till höger (varje steg betyder "dividera med två")

Bitförskjutning i PHP är aritmetisk. Bitar som förskjuts ut från antingen änden kastas bort. Vänsterförskjutningar har nollor som förskjuts in på höger sida medan teckenbiten förskjuts ut på vänster sida, vilket betyder att tecknet på en operand inte bevaras. Högerförskjutningar har kopior av teckenbiten som förskjuts in på vänster sida, vilket betyder att tecknet på en operand bevaras.

Använd parenteser för att säkerställa önskat företräde. Till exempel, $a & $b == true utvärderar likheten sedan den bitvisa och; medan ($a & $b) == true utvärderar den bitvisa och sedan likheten.

Om båda operanderna för &-, |- och ^-operatorerna är strängar, kommer operationen att utföras på ASCII-värdena för tecknen som utgör strängarna och resultatet kommer att vara en sträng. I alla andra fall konverteras båda operanderna till heltal och resultatet blir ett heltal.

Om operanden för ~-operatorn är en sträng, utförs operationen på ASCII-värdena för tecknen som utgör strängen och resultatet blir en sträng, annars behandlas operanden och resultatet som heltal.

Både operanderna och resultatet för <<- och >>-operatorerna behandlas alltid som heltal.

PHP:s error_reporting ini-inställning använder bitvisa värden, vilket ger en demonstration från verkliga livet av att stänga av bitar. För att visa alla fel, förutom notiser, säger instruktionerna i php.ini-filen att använda: E_ALL & ~E_NOTICE

Detta fungerar genom att starta med E_ALL: 00000000000000000111011111111111 Sedan tar man värdet av E_NOTICE... 00000000000000000000000000001000 ... och inverterar det via ~: 11111111111111111111111111110111 Slutligen använder den AND (&) för att hitta bitarna som är påslagna i båda värdena: 00000000000000000111011111110111

Ett annat sätt att åstadkomma detta är att använda XOR (^) för att hitta bitar som är påslagna i endast ett värde eller det andra: E_ALL ^ E_NOTICE

error_reporting kan också användas för att demonstrera att slå på bitar. Sättet att visa bara fel och återställbara fel är: E_ERROR | E_RECOVERABLE_ERROR

Denna process kombinerar E_ERROR 00000000000000000000000000000001 och 00000000000000000001000000000000 med hjälp av OR (|)-operatorn för att få bitarna påslagna i antingen värde: 00000000000000000001000000000001

Exempel

Exempel #1 Bitvisa AND, OR och XOR-operationer på heltal <?php /*

* Ignorera den övre sektionen,
* det är bara formatering för att göra utskriften tydligare.
*/

$format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)'

       . ' %3$s (%4$2d = %4$04b)' . "\n";

echo <<<EOH

---------     ---------  -- ---------
resultat        värde      op test
---------     ---------  -- ---------

EOH;


/*

* Här är exemplen.
*/

$värden = array(0, 1, 2, 4, 8); $test = 1 + 4;

echo "\n Bitvis AND \n"; foreach ($värden as $värde) {

   $resultat = $värde & $test;
   printf($format, $resultat, $värde, '&', $test);

}

echo "\n Bitvis Inklusiv OR \n"; foreach ($värden as $värde) {

   $resultat = $värde | $test;
   printf($format, $resultat, $värde, '|', $test);

}

echo "\n Bitvis Exklusiv OR (XOR) \n"; foreach ($värden as $värde) {

   $resultat = $värde ^ $test;
   printf($format, $resultat, $värde, '^', $test);

} ?> Ovanstående exempel kommer att skriva ut:

---------     ---------  -- ---------
resultat        värde      op test
---------     ---------  -- ---------
Bitvis AND

( 0 = 0000) = ( 0 = 0000) & ( 5 = 0101) ( 1 = 0001) = ( 1 = 0001) & ( 5 = 0101) ( 0 = 0000) = ( 2 = 0010) & ( 5 = 0101) ( 4 = 0100) = ( 4 = 0100) & ( 5 = 0101) ( 0 = 0000) = ( 8 = 1000) & ( 5 = 0101)

Bitvis Inklusiv OR

( 5 = 0101) = ( 0 = 0000) | ( 5 = 0101) ( 5 = 0101) = ( 1 = 0001) | ( 5 = 0101) ( 7 = 0111) = ( 2 = 0010) | ( 5 = 0101) ( 5 = 0101) = ( 4 = 0100) | ( 5 = 0101) (13 = 1101) = ( 8 = 1000) | ( 5 = 0101)

Bitvis Exklusiv OR (XOR)

( 5 = 0101) = ( 0 = 0000) ^ ( 5 = 0101) ( 4 = 0100) = ( 1 = 0001) ^ ( 5 = 0101) ( 7 = 0111) = ( 2 = 0010) ^ ( 5 = 0101) ( 1 = 0001) = ( 4 = 0100) ^ ( 5 = 0101) (13 = 1101) = ( 8 = 1000) ^ ( 5 = 0101) Exempel #2 Bitvisa XOR-operationer på strängar

<?php echo 12 ^ 9; // Skriver ut '5'

echo "12" ^ "9"; // Skriver ut tecknet Backspace (ascii 8)

                // ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8

echo "hallo" ^ "hello"; // Skriver ut ascii-värdena #0 #4 #0 #0 #0

                       // 'a' ^ 'e' = #4

echo 2 ^ "3"; // Skriver ut 1

             // 2 ^ ((int)"3") == 1

echo "2" ^ 3; // Skriver ut 1

             // ((int)"2") ^ 3 == 1

?> Exempel #3 Bitförskjutning på heltal

<?php /*

* Här är exemplen.
*/

echo "\n--- BIT SHIFT RIGHT ON POSITIVE INTEGERS ---\n";

$val = 4; $places

= 1;

$res = $val >> $places; p($res, $val, '>>', $places, 'copy of sign bit shifted into left side');

$val = 4; $places = 2; $res = $val >> $places; p($res, $val, '>>', $places);

$val = 4; $places = 3; $res = $val >> $places; p($res, $val, '>>', $places, 'bits shift out right side');

$val = 4; $places = 4; $res = $val >> $places; p($res, $val, '>>', places, 'same result as above; can not shift beyond 0');


echo "\n--- BIT SHIFT RIGHT ON NEGATIVE INTEGERS ---\n";

$val = -4; $places = 1; $res = $val >> $places; p($res, $val, '>>', $places, 'copy of sign bit shifted into left side');

$val = -4; $places = 2; $res = $val >> $places; p($res, $val, '>>', $places, 'bits shift out right side');

$val = -4; $places = 3; $res = $val >> $places; p($res, $val, '>>', $places, 'same result as above; can not shift beyond -1');


echo "\n--- BIT SHIFT LEFT ON POSITIVE INTEGERS ---\n";

$val = 4; $places = 1; $res = $val << $places; p($res, $val, '<<', $places, 'zeros fill in right side');

$val = 4; $places = (PHP_INT_SIZE * 8) - 4; $res = $val << $places; p($res, $val, '<<', $places);

$val = 4; $places = (PHP_INT_SIZE * 8) - 3; $res = $val << $places; p($res, $val, '<<', $places, 'sign bits get shifted out');

$val = 4; $places = (PHP_INT_SIZE * 8) - 2; $res = $val << $places; p($res, $val, '<<', $places, 'bits shift out left side');


echo "\n--- BIT SHIFT LEFT ON NEGATIVE INTEGERS ---\n";

$val = -4; $places = 1; $res = $val << $places; p($res, $val, '<<', $places, 'zeros fill in right side');

$val = -4; $places = (PHP_INT_SIZE * 8) - 3; $res = $val << $places; p($res, $val, '<<', $places);

$val = -4; $places = (PHP_INT_SIZE * 8) - 2; $res = $val << $places; p($res, $val, '<<', $places, 'bits shift out left side, including sign bit');


/*

* Ignorera denna nedre sektion,
* det är bara formatering för att göra utskriften tydligare.
*/

function p($res, $val, $op, $places, $note = ) {

   $format = '%0' . (PHP_INT_SIZE * 8) . "b\n";
   printf("Expression: %d = %d %s %d\n", $res, $val, $op, $places);
   echo " Decimal:\n";
   printf("  val=%d\n", $val);
   printf("  res=%d\n", $res);
   echo " Binary:\n";
   printf('  val=' . $format, $val);
   printf('  res=' . $format, res);
   if ($note) {
       echo " NOTE: $note\n";
   }
   echo "\n";

} ?> Output of the above example on 32 bit machines:


--- BIT SHIFT RIGHT ON POSITIVE INTEGERS --- Expression: 2 = 4 >> 1

Decimal:
 val=4
 res=2
Binary:
 val=00000000000000000000000000000100
 res=00000000000000000000000000000010
NOTE: copy of sign bit shifted into left side

Expression: 1 = 4 >> 2

Decimal:
 val=4
 res=1
Binary:
 val=00000000000000000000000000000100
 res=00000000000000000000000000000001

Expression: 0 = 4 >> 3

Decimal:
 val=4
 res=0
Binary:
 val=00000000000000000000000000000100
 res=00000000000000000000000000000000
NOTE: bits shift out right side

Expression: 0 = 4 >> 4

Decimal:
 val=4
 res=0
Binary:
 val=00000000000000000000000000000100
 res=00000000000000000000000000000000
NOTE: same result as above; can not shift beyond 0


--- BIT SHIFT RIGHT ON NEGATIVE INTEGERS --- Expression: -2 = -4 >> 1

Decimal:
 val=-4
 res=-2
Binary:
 val=11111111111111111111111111111100
 res=11111111111111111111111111111110
NOTE: copy of sign bit shifted into left side

Expression: -1 = -4 >> 2

Decimal:
 val=-4
 res=-1
Binary:
 val=11111111111111111111111111111100
 res=11111111111111111111111111111111
NOTE: bits shift out right side

Expression: -1 = -4 >> 3

Decimal:
 val=-4
 res=-1
Binary:
 val=11111111111111111111111111111100
 res=11111111111111111111111111111111
NOTE: same result as above; can not shift beyond -1


--- BIT SHIFT LEFT ON POSITIVE INTEGERS --- Expression: 8 = 4 << 1

Decimal:
 val=4
 res=8
Binary:
 val=00000000000000000000000000000100
 res=00000000000000000000000000001000
NOTE: zeros fill in right side

Expression: 1073741824 = 4 << 28

Decimal:
 val=4
 res=1073741824
Binary:
 val=00000000000000000000000000000100
 res=01000000000000000000000000000000

Expression: -2147483648 = 4 << 29

Decimal:
 val=4
 res=-2147483648
Binary:
 val=00000000000000000000000000000100
 res=10000000000000000000000000000000
NOTE: sign bits get shifted out

Expression: 0 = 4 << 30

Decimal:
 val=4
 res=0
Binary:
 val=00000000000000000000000000000100
 res=00000000000000000000000000000000
NOTE: bits shift out left side


--- BIT SHIFT LEFT ON NEGATIVE INTEGERS --- Expression: -8 = -4 << 1

Decimal:
 val=-4
 res=-8
Binary:
 val=11111111111111111111111111111100
 res=11111111111111111111111111111000
NOTE: zeros fill in right side

Expression: -9223372036854775808 = -4 << 29

Decimal:
 val=-4
 res=-9223372036854775808
Binary:
 val=11111111111111111111111111111100
 res=10000000000000000000000000000000

Expression: 0 = -4 << 30

Decimal:
 val=-4
 res=0
Binary:
 val=11111111111111111111111111111100
 res=00000000000000000000000000000000
NOTE: bits shift out left side, including sign bit

Output of the above example on 64 bit machines:


--- BIT SHIFT RIGHT ON POSITIVE INTEGERS --- Expression: 2 = 4 >> 1

Decimal:
 val=4
 res=2
Binary:
 val=0000000000000000000000000000000000000000000000000000000000000100
 res=0000000000000000000000000000000000000000000000000000000000000010
NOTE: copy of sign bit shifted into left side

Expression: 1 = 4 >> 2

Decimal:
 val=4
 res=1
Binary:
 val=0000000000000000000000000000000000000000000000000000000000000100
 res=000000000000

Varning

Använd funktioner från gmp-tillägget för bitvis manipulation på tal som överstiger PHP_INT_MAX.

Se också

  • pack() - Packar data till en binär sträng.
  • unpack() - Packar upp data från en binär sträng.
  • gmp_and() - Utför en bitvis AND-operation på två stora tal.
  • gmp_or() - Utför en bitvis OR-operation på två stora tal.
  • gmp_xor() - Utför en bitvis XOR-operation på två stora tal.
  • gmp_testbit() - Testar om en specifik bit är satt i ett stort tal.
  • gmp_clrbit() - Rensar en specifik bit i ett stort tal.


PHP
Språkreferens
Sidan är översatt ifrån :

https://www.php.net/manual/en/language.operators.bitwise.php