PHP ビット演算子

WBOY
リリース: 2016-07-30 13:30:44
オリジナル
1267 人が閲覧しました

ビット演算子を使用すると、整数内の指定されたビットの評価と操作が可能になります。

ビット演算子
example name result
$a & $b<codefira mono code pro word-wrap:break-word>$a & $b</codefira></codefira></span></td> <td>And(按位与)</td> <td>将把 <var>$a</var> 和 <var>$b</var> 中都为 1 的位设为 1。</td> </tr> <tr> <td><span><codefira mono code pro word-wrap:break-word>$a | $b</codefira></span></td> <td>Or(按位或)</td> <td>将把 <var>$a</var> 和 <var>$b</var> 中任何一个为 1 的位设为 1。</td> </tr> <tr> <td><span><codefira mono code pro word-wrap:break-word>$a ^ $b</codefira></span></td> <td>Xor(按位异或)</td> <td>将把 <var>$a</var> 和 <var>$b</var> 中一个为 1 另一个为 0 的位设为 1。</td> </tr> <tr> <td><span><codefira mono code pro word-wrap:break-word>~ $a</codefira></span></td> <td>Not(按位取反)</td> <td>将 <var>$a</var> 中为 0 的位设为 1,反之亦然。</td> </tr> <tr> <td><span><codefira mono code pro word-wrap:break-word>$a << $bShift left(左移)$a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)。
$a >> $b</codefira></span></td>And (ビット単位の AND) <td></td> は、<td>$a<var> と </var>$b<var> のビットをどちらも 1 対 1 に設定します。 </var> </td> </tr> </tbody> </table> <codefira mono>$a | $b🎜🎜🎜Or (ビット単位の OR) 🎜🎜 は 🎜$a🎜 または 🎜$b🎜 のいずれかを置き換えます 1 のビットは1に設定します。 🎜🎜🎜🎜🎜<codefira mono code pro word-wrap:break-word>$a ^ $b🎜🎜🎜Xor (ビットごとの XOR)🎜🎜 はビットを設定します🎜$a🎜 と 🎜$b🎜 の一方は 1、もう一方は 0 を 1 にします。 🎜🎜🎜🎜🎜<codefira mono code pro> ~ $a🎜🎜🎜Not (ビット単位の否定)🎜🎜は、🎜$a🎜の0であるビットを1に設定し、その逆も同様です。 🎜🎜🎜🎜🎜<codefira mono code pro word-wrap:break-word>$a << $b🎜🎜🎜左にシフト🎜🎜 ビットを移動します🎜$a🎜 を左に 🎜$b🎜 回 (各移動は「2 を掛ける」を意味します) 🎜🎜🎜🎜🎜$ > は「2 で割る」を意味します)。 🎜🎜🎜🎜

ディスプレイスメントは、PHP の数学演算です。いずれかの方向に移動されたビットは破棄されます。左にシフトすると、右側にゼロが埋め込まれ、符号ビットが移動されます。これは、符号が保持されないことを意味します。右にシフトすると、左側に符号ビットが埋め込まれます。これは、符号が保持されることを意味します。

希望の優先順位を確保するには括弧を使用します。たとえば、$a & $b == true は最初に比較してからビット単位の AND を実行しますが、($a & $b) == true は最初にビット単位の AND を実行してから比較します。

データ型の変換に注意してください。左引数と右引数の両方が文字列の場合、ビット単位の演算子は文字の ASCII 値を操作します。

PHP 的 ini 设定 error_reporting 使用了按位的&#20540;,
提供了关闭某个位的真实例子。要显示除了提示级别
之外的所有错误,php.ini 中是这样用的:
<span><codeFira Mono','Source Code Pro',monospace; word-wrap:break-word">E_ALL & ~E_NOTICE</code></span>
ログイン後にコピー
具体运作方式是先取得 E_ALL 的&#20540;:
<span>00000000000000000111011111111111</span>
再取得 E_NOTICE 的&#20540;:
<span>00000000000000000000000000001000</span>
然后通过 <span>~</span> 将其取反:
<span>11111111111111111111111111110111</span>
最后再用按位与 AND(&)得到两个&#20540;中都设定了(为 1)的位:
<span>00000000000000000111011111110111</span>
ログイン後にコピー
另外一个方法是用按位异或 XOR(<span>^</span>)来取得只在
其中一个&#20540;中设定了的位:
<span><codeFira Mono','Source Code Pro',monospace; word-wrap:break-word">E_ALL ^ E_NOTICE</code></span>
ログイン後にコピー

例 #1 整数の AND、OR、および XOR 演算子

/*
* Ignore the top section,
* it is just formatting to make output clearer.
*/
$format = '(%1d = %1b) = (%2d = %2b)'
. ' %3$s (%4d = %4b)' . "n";
echo <<
--------- --------- -- ---------
result value op test
--------- --------- -- ---------
EOH;
/*
* Here are the examples.
*/
$values = array(0, 1, 2, 4, 8);
$test = 1 + 4;
echo
"n Bitwise AND n";
foreach (
$values as $value) {
$result = $value & $test;
printf($format, $result, $value, '&', $test);
}
echo
"n Bitwise Inclusive OR n";
foreach (
$values as $value) {
$result = $value | $test;
printf($format, $result, $value, '|', $test);
}
echo
"n Bitwise Exclusive OR (XOR) n";
foreach (
$values as $value) {
$result = $value ^ $test;
printf($format, $result, $value, '^', $test);
}
?>/*
* 上のセクションは無視してください。
* 出力をわかりやすくするための単なる書式設定です。
*/

$format

=

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

' %3$s (%4$2d = % 4) $04b)'

"n";
エコー <<

🎜 --------- --------- - - --------
結果
🎜🎜EOH;
🎜🎜/*
* 以下は例です。
*/
🎜🎜$values 🎜🎜= array(🎜🎜0🎜🎜, 🎜🎜1🎜 🎜, 🎜🎜2🎜🎜, 🎜🎜4🎜🎜, 🎜🎜8🎜🎜);
🎜🎜$test 🎜🎜= 🎜🎜1 🎜🎜+ 🎜🎜4🎜 🎜;
echo 🎜🎜" n ビット単位 AND n"🎜🎜;
foreach (🎜🎜$values 🎜🎜as 🎜🎜$value🎜🎜) {
🎜 🎜$結果 🎜🎜= 🎜🎜$値 🎜🎜& 🎜🎜$test🎜 🎜;
🎜🎜printf🎜🎜(🎜🎜$format🎜🎜, 🎜🎜$価値🎜🎜、 🎜🎜'&'🎜🎜, 🎜 🎜$test🎜🎜);
}
echo 🎜🎜"n ビット単位包含 OR n"🎜🎜;
foreach (🎜🎜$values 🎜🎜として🎜🎜$value🎜🎜) {
🎜🎜$result 🎜🎜= 🎜🎜 $value 🎜🎜$test🎜🎜;
🎜🎜printf🎜🎜(🎜🎜$format 🎜🎜、🎜🎜 $result🎜🎜, 🎜🎜$value🎜🎜, 🎜🎜'|'🎜🎜, 🎜🎜$test🎜🎜);
}
echo 🎜🎜"n ビットごとの排他的論理和 (XOR) n"🎜🎜 ;
foreach (🎜🎜$values 🎜🎜as 🎜🎜$value🎜🎜) {
🎜🎜$result 🎜🎜= 🎜🎜$value 🎜🎜^ 🎜🎜$test🎜🎜;
🎜🎜printf🎜🎜(🎜🎜$format🎜🎜, 🎜🎜$result🎜🎜, 🎜🎜 $value🎜🎜, 🎜🎜'^'🎜🎜, 🎜🎜$test🎜🎜);
}
🎜🎜?>🎜🎜🎜🎜🎜🎜上記のルーチンは出力します: 🎜 🎜🎜🎜

error_reporting 也可用来演示怎样置位。只显示错误和可恢复
错误的方法是:
<span><codefira mono code pro word-wrap:break-word>E_ERROR | E_RECOVERABLE_ERROR</codefira></span>
ログイン後にコピー
🎜🎜🎜🎜🎜🎜例 #2 文字列 XOR 演算子🎜🎜

echo 12 ^ 9; // Outputs '5'
echo "12" ^ "9"; // Outputs the Backspace character (ascii 8)
// ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8
echo "hallo" ^ "hello"; // Outputs the ascii values #0 #4 #0 #0 #0
// 'a' ^ 'e' = #4
echo 2 ^ "3"; // Outputs 1
// 2 ^ ((int)"3") == 1
echo "2" ^ 3; // Outputs 1
// ((int)"2") ^ 3 == 1
?>

例 #3 整数の置換

/*
* 例を次に示します。
*/
echo "n--- 正の整数を右にビットシフト ---n";
$val < span>=
4;
$places = 1;
$res = $val >> span>$places;
p($res, span>$val, '>>', $places,'符号ビットのコピーが左側にシフトされました');
$val = 4;
$places = 2 ;
$res = $val >> $places ;
p($res, $val, '>>', $places);
$val = 4;
$places span>= 3;
$res = $ val >> $places;
p($res
$val'>>'$places ,'ビットは右側にシフトアウト');
$val = 4;
$places = 4;
$res = $val >> $places;
p($res$val'>>'$places の結果は上記と同じです。0 を超えてシフトすることはできません。);
echo
"n- -- 負の整数の右ビットシフト ---n";
$val = -4 ;
$places = 1;
$res = $val >> $places;
p($res$val'>>'$places ,'符号ビットのコピーが左側にシフトされました');
$val = -4;
$places = 2;
$res = $val >> $places;
p($res
$val'>>'$places ,'ビットは右側にシフトアウト');
$val = -4;
$places = 3 ;
$res = $val >> $places;
p($res$val'>>'$places の結果は上記と同じです。-1 を超えてシフトすることはできません。);
echo
"n --- 正の整数で左ビットシフト ---n";
$val = 4 ;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'ゼロを埋める右側') ;
$val = 4;
$places = (PHP_INT_SIZE * 8) - 4;
$res = $val << $places;
p($res, $val, '<<', $places );
$val = 4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $ヴァル<< $places;
p($res, $val, '<<', $places のサインビットはシフトアウトされます');
$val = 4;
$places = (PHP_INT_SIZE * 8) - 2 ;
$res = $val << $places;
p($res, $val, '<<', $places のビット左側をシフトアウト');
エコー
"n--- 負の整数で左ビットシフト ---n";
$val = -4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places のゼロ右側に記入してください');
$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 のビット符号ビットを含む左側をシフトアウトします);
/*
* この下部セクションは無視してください。
* これは、出力を明確にするための単なる書式設定です。
*/
関数 p ( $res$val$op$places$note = '') {
$形式 = '%0' 。 (PHP_INT_SIZE * 8) 。 「ブン」;
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";
}
?>

以上例程在 32 位机器上的输出:

--- 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: -2147483648 = -4 << 29
 Decimal:
  val=-4
  res=-2147483648
 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
ログイン後にコピー

以上例程在 64 位机器上的输出:

--- 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=0000000000000000000000000000000000000000000000000000000000000001

Expression: 0 = 4 >> 3
 Decimal:
  val=4
  res=0
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=0000000000000000000000000000000000000000000000000000000000000000
 NOTE: bits shift out right side

Expression: 0 = 4 >> 4
 Decimal:
  val=4
  res=0
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=0000000000000000000000000000000000000000000000000000000000000000
 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=1111111111111111111111111111111111111111111111111111111111111100
  res=1111111111111111111111111111111111111111111111111111111111111110
 NOTE: copy of sign bit shifted into left side

Expression: -1 = -4 >> 2
 Decimal:
  val=-4
  res=-1
 Binary:
  val=1111111111111111111111111111111111111111111111111111111111111100
  res=1111111111111111111111111111111111111111111111111111111111111111
 NOTE: bits shift out right side

Expression: -1 = -4 >> 3
 Decimal:
  val=-4
  res=-1
 Binary:
  val=1111111111111111111111111111111111111111111111111111111111111100
  res=1111111111111111111111111111111111111111111111111111111111111111
 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=0000000000000000000000000000000000000000000000000000000000000100
  res=0000000000000000000000000000000000000000000000000000000000001000
 NOTE: zeros fill in right side

Expression: 4611686018427387904 = 4 << 60
 Decimal:
  val=4
  res=4611686018427387904
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=0100000000000000000000000000000000000000000000000000000000000000

Expression: -9223372036854775808 = 4 << 61
 Decimal:
  val=4
  res=-9223372036854775808
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=1000000000000000000000000000000000000000000000000000000000000000
 NOTE: sign bits get shifted out

Expression: 0 = 4 << 62
 Decimal:
  val=4
  res=0
 Binary:
  val=0000000000000000000000000000000000000000000000000000000000000100
  res=0000000000000000000000000000000000000000000000000000000000000000
 NOTE: bits shift out left side


--- BIT SHIFT LEFT ON NEGATIVE INTEGERS ---
Expression: -8 = -4 << 1
 Decimal:
  val=-4
  res=-8
 Binary:
  val=1111111111111111111111111111111111111111111111111111111111111100
  res=1111111111111111111111111111111111111111111111111111111111111000
 NOTE: zeros fill in right side

Expression: -9223372036854775808 = -4 << 61
 Decimal:
  val=-4
  res=-9223372036854775808
 Binary:
  val=1111111111111111111111111111111111111111111111111111111111111100
  res=1000000000000000000000000000000000000000000000000000000000000000

Expression: 0 = -4 << 62
 Decimal:
  val=-4
  res=0
 Binary:
  val=1111111111111111111111111111111111111111111111111111111111111100
  res=0000000000000000000000000000000000000000000000000000000000000000
 NOTE: bits shift out left side, including sign bit
ログイン後にコピー

Warning

不要在 32 位系统下向右移超过 32 位。不要在结果可能超过 32 的情况下左移。使用 gmp 扩展对超出 PHP_INT_MAX 的数值来进行位操作。

参见 pack()unpack()gmp_and()gmp_or()gmp_xor()gmp_testbit()gmp_clrbit()

add a note add a note

User Contributed Notes 43 notes

up

down

46

wbcarts at juno dot com ?
3 years ago

カスタム用のビットワイズフラグ PHP オブジェクト
場合によっては、複数のブール値 TRUE または FALSE 値を保持するカスタム PHP オブジェクトが必要になります。それぞれに簡単に変数を含めることもできますが、いつものように、コードはすぐに扱いにくくなる可能性があります。よりインテリジェントなアプローチが常に答えであるように思えます。 最初はやりすぎだと思われる場合は、
$flags と呼ばれる単一の整数変数を保持する抽象基本クラスから始めます。この単純な整数には、32 個の TRUE または FALSE のブール値を保持できます。もう 1 つ考慮すべきことは、他の BITS を妨げずに特定の BIT 値を設定することです。 そのため、選択したビットのみを設定する setFlag($flag, $value) 関数がクラス定義に含まれています。抽象基本クラスの定義は次のとおりです:
# BitwiseFlag.php
abstract class BitwiseFlag
{
protected
$flags;
/*
* 注:これらの関数は、外部コード
* が誤って BITS を設定するのを防ぐために保護されています。拡張クラス「User」
* がこれをどのように処理するかを見てください。
*
*/
保護関数 isFlagSet($flag)
{
return ((
$this -> ;フラグ & $フラグ) == $flag);
}
保護された関数
setFlag($flag, $value)
{
if(
) $value)
{
$this->flags |= $flag;
}
else
{
$this-> ;フラグ &= ~$flag;
}
}
}
?>

上記のクラスは抽象クラスでインスタンス化できないため、拡張機能が必要です。以下は User という単純な拡張機能です -- わかりやすくするために大幅に切り詰められています。 const変数とそれらを使用する方法を定義していることに注意してください。
BitwiseFlag
{ const
FLAG_REGISTERED = 1
// $flags のビット #1 の値は 1 const
FLAG_ACTIVE
=
2;     // $flags のビット #2 の値は 2 const FLAG_MEMBER
= 4;     // $flags のビット #3 の値は 4 const FLAG_ADMIN
= 8;      // $flags のビット #4 の値は 8 です public function isRegistered
(){ return $this->isFlagSet() 自分
: :FLAG_REGISTERED); }
public function
isActive(){ return $this->isFlagSet() 自分
::
FLAG_ACTIVE ); }
public function
isMember(){ return $this->isFlagSet(self
::
FLAG _MEMBER); }
public function
isAdmin(){ return $this->isFlagSet(self
::
FLAG_ADMIN); }
public function
setRegistered ($value){ $this->setFlag
(
self::FLAG_REGISTERED,
$値
); }
public function setActive($value){
$this->setFlag(self:: FLAG_ACTIVE$value );
}
public function
setMember($value){
$this->setFlag( 自分::FLAG_MEMBER , $value);
}
public function
setAdmin($value){
$this->setFla g(自分 ::FLAG_ADMIN, $value);
}
public function
__toString(){
return
'User [' .
(
$this-> ;は登録されました() ? 「登録済み」 : '') .
(
$this->はアクティブです() ? 「アクティブ」: '') .
(
$this->はメンバーです() ? 「メンバー」: '') .
(
$this->はAdmin() ? 「管理者」: '') .
']';
}
}
?>

これは大変な作業のように思えますが、多くの問題に対処しました。たとえば、コードの使用と保守は簡単です。フラグ値の取得と設定には意味があります。 User クラスを使用すると、ビット単位のフラグ操作がいかに簡単で直感的であるかがわかります。 become.
require('User.php')
$user = new User();
$user -> setRegistered(tru​​e);
$user->setActive(tru​​e);
$ユーザー->メンバーを設定 (tru​​e);
$user->setAdmin(tru​​e);echo
$user;  // 出力: ユーザー [登録アクティブメンバー管理者]
?>

up

down

6
zlel grxnslxves13 at hotmail dot com~=s/x/ee/g ?
9年前

エリック・スワンソンのことを指します Perl VS PHP の xor 実装に関する投稿。 
実際には、これは XOR の実装に関する問題ではなく、PHP が採用する型負けポリシーに大きく関係しています。 
int と float を自由に切り替えることはほとんどの場合に適していますが、値がマシンのワード サイズに近い場合に問題が発生します。つまり、32 ビット マシンでは、0x80000000 付近の値で問題が発生します。これは主に PHP が原因です。 は符号なし整数をサポートしていません。
bindec/decbin を使用すると、unsigned-int xor を実行するための回避策としてこの問題に対処できますが、実際の状況は次のとおりです (このコードのパフォーマンスが向上するとは主張していませんが、これはより良い教育的コード):
function unsigned_xor32 ($a, $b)
{
$a1 = $a & 0x7FFF0000;
$a2 = $a & 0x0000FFFF;
$a3 = $a & 0x80000000;
$b1 = $b & 0x7FFF0000;
$b2 = $b & 0x0000FFFF;
$b3 = $b & 0x80000000;
$c = ($a3 != $b3 ) ? 0x80000000 : 0;
return ((
$a1 ^ $b1) |($a2 ^ $b2)) + $c;
}
$x = 3851235679;
$y = 43814 ;
エコー
"
これは必要な値"
;
echo
"
3851262585"
;
echo
"
整数値に対するネイティブ XOR 演算の結果は、符号付き整数として扱われます。"
;
echo
"
"
.($x ^ $y);
echo
"
したがって、MSBを個別に実行します"
;
eチョー
"
"
.unsigned_xor32($x, $y);
?>

これ本当に基礎的なことですが、それらのために大学時代にこれを見逃した人は、ここに 2 の補数に関する何かがあるようです:
http://www.evergreen.edu/biophysics/technotes/program/2s_comp.htm

up

down

3たるみ ichドットネット で?
2年前

ビットごとの再実装 NOT (~)
protected function flipBin($number) {
$bin = str_pad(base_convert($number, 10, 2), 32, 0, STR_PAD_LEFT);
for ($i = 0; $i switch ($bin{$i}) {
case '0' :
$bin{$i} = '1';
ブレーク;
case '1' :
$bin{$i} = '0';
Break;
}
}
return binding($bin);
}
利点は、MAX_INT より大きい数値でも動作することです

アップ

ダウン

3ヴィベカナンド dot pathak25 at gmail dot com ?
2 年前

$a =     9;
$b =     10;
echo $a & $b;
place value   128  64  32  16   8  4   2   1
$a                     0      0    0     0    1  0   0   1   =9
$b                     0      0    0     0    1   0  1   0   =10
result   8  
only bit they share together is the 8 bit. So 8 gets returned.
  $a =     36;
$b =     103;
echo $a & $b;
place value   128  64  32  16   8    4   2   1
$a                     0      0    1     0    0    1   0   0   =36
$b                     0      1    1     0    0    1   1   1   =103
result  32+4 = 36
the only bits these two share together are the bits 32 and 4 which when added together return 36.
$a =     9;
$b =     10;
echo $a | $b;
place value   128  64  32  16   8  4   2   1
$a                     0      0    0     0    1  0   0   1   =9
$b                     0      0    0     0    1   0  1   0   =10
result 8+2+1 = 11
3 bits set, in the 8, 2, and 1 column.add those up 8+2+1 and you get 11
$a =     9;
$b =     10;
echo $a ^ $b;
place value   128  64  32  16   8  4   2   1
$a                     0      0    0     0    1  0   0   1   =9
$b                     0      0    0     0    1   0  1   0   =10
result  2+1 = 3
the 2 bit and the 1 bit that they each have set but don't share. Soooo 2+1 = 3
$a = 9;

$b = 10;echo $a & $b;位の値 128 64 32 16 8 4 2 1

$a 0 0 0 0 1 0 0 1 =9

$b 0 0 0 0 1 0 1 0 =10

結果 8

一緒に共有するビットは 8 ビットだけです。したがって、8 が返されます。

$a = 36;

$b = 103;
echo $a & $b;place value 128 64 32 16 8 4 2 1$a 0 0 1 0 0 1 0 0 =36 $b 0 1 1 0 0 1 1 1 =103結果 32+4 = 36これら 2 つが共有するビットは 32 と 4 だけで、合計すると 36 が返されます。$a = 9;
$b = 10;エコー $a | $b;位の値 128 64 32 16 8 4 2 1$a 0 0 0 0 1 0 0 1 =9

$b 0 0 0 0 1 0 1 0 =10

結果 8+2+1 = 11 8、2、1 列に 3 ビットが設定されています。これらを 8+2+1 に加算すると 11 になります$a = 9;
$b = 10;
echo $a ^ $b;
place value 128 64 32 16 8 4 2 1$a 0 0 0 0 1 0 0 1 =9

$b 0 0 0 0 1 0 1 0 =10結果 2+1 = 3その2ビットと1ビットそれぞれ設定されていますが、共有されていません。すごい 2+1 = 3

3
エリッチ シーチャワイ・ドットコム🎜 で? 🎜🎜2年前🎜🎜🎜🎜🎜🎜ネガティブなことについてのメモ ドキュメントに記載されているように、シフト値は整数の 2 による乗算または除算 (左または右) です。つまり、負のシフト値 (右側のオペランド) はシフトの符号に影響し、シフトの方向には影響しません。私は...するだろう 期待している。  🎜フェ。 0xff >> -2 は 0x0 🎜 および 0xff << になります。 -2 の結果は 0xFFFFFFFFC0000000 になります (PHP_INT_MAX に依存) Gmail ドットコム🎜🎜 で? 🎜🎜6年前🎜🎜

お探しの方へ 負の値で動作する PHP の循環ビット シフト関数 (特に暗号関数に便利) について、私が書いた小さな関数を以下に示します:
(注: これを負の $num 値で動作させるまでにほぼ丸一日かかりました) (なぜうまくいくときとうまくいかないときがあるのか​​わかりませんでした)。PHP には算術演算のみがあり、私が慣れ親しんでいる論理的なビット単位の右シフト (0x80000001>>16) がないからです。 予想どおり、「0000 0000 0000 0000 1000 0000 0000 0000」ではなく、「1111 1111 1111 1111 1000 0000 0000 0000」を(バイナリで)出力します。これを修正するには、オフセットより 1 つ少ない右シフト 0x7FFFFFFF に等しいマスクを (ビットごとの & によって) 適用する必要があります。 )
function circular_shift($num,$offset) { //非破壊循環ビット単位シフトを実行します。オフセットの場合は正のシフト、負の場合は右シフトします
$num=(int)$num;
$mask= 0x7fffffff//マスク PHP は算術右シフトのみを実行し、論理的ではないという事実に対応するため、つまり、PHP は負の値を右シフトするときに期待される出力を提供しません
if ($offset>0) {
$num=($num<<$offset%32) | (($num>>(32-$offset%32)) & ($mask>>(31-$offset%32)));
}
elseif (
$offset 0){
$offset=abs($offset);
$num=(( $num>>$オフセット%32) & ($マスク>>(-1+$offset%32))) | ($ $num&lt;&lt;(32-$offset32); }

?>


下3

m0sh hotmail ドットコム

で?

7年前

@greenone - 素晴らしい機能です。 ありがとう。キーの使用法に合わせて調整しました:
function bitxor($str, $key) {
$xorWidth = PHP_INT_SIZE*8;
// 分割
$o1 = str_split($str, $xorWidth);
$o2 = str_split(str_pad('', strlen) ($str)、$ key)、$xorWidth);
$res = '';
$runs = count ($o1);
for(
$i=0;$i<$runs;$i++)
$res .= decbin(bindec($o1[$i]) ^ bindec($o2[$i]));       
return
$res;
}
?>

3Eリック スワンソン ?
9年前

PerlとPHPの実装 ^ 演算子の説明:
Perl モジュールを PHP に変換しようとした後、Perl の ^ 演算子の実装が PHP の実装とは異なることに気付きました。  デフォルトでは、Perl は変数を浮動小数点として扱い、PHP は整数として扱います。  PHPの使用を確認できました 「整数を使用する」と演算子を指定します。 Perl モジュール内では、PHP が使用していたものとまったく同じ結果が出力されます。
PHP で ^ 演算子を使用する場合、論理的な決定は、すべての変数を (float) としてキャストすることです。  ただし、これでは同じ結果は得られません。  30分ほど壁に頭をぶつけ続けた後、宝石を発見し、 PHP での 2 進数と 10 進数の変換
/*
ビット単位の演算の経験があまりないので、これが最良の解決策であるとは言えませんが、最終的には確実に機能し、常に Perl が提供するのとまったく同じ結果を返す解決策であることは確かです。
*/
function binxor($a, $b) {
return binding(decbin((float)$a ^ (float)$b));
}
//通常の PHP コードでは Perl と同じ結果は得られません
$結果 = 3851235679 ^ 43814; //= -443704711
//Perl と同じ結果を取得するには
$result = binxor(3851235679, 43814); //= 3851262585
//YIPPEE!!!
//違いを確認するには、次のことを試してください
$a = 3851235679 XOR 43814;
$b = 3851235679 ^ 43814; //整数の結果
$c = (float)3851235679 ^ (float)43814; // $b
$d = binxor(3851235679, 43814) と同じ; //Perlと同じ!!
echo("A: $a
");
echo("B: $b
");
echo("C: $c
");
echo("D: $d
");

10グレイダ DONTSPAM dot Solidinc dot org の dot NOSPAM ?
6年前

最初に、ビットマスキングを見つけました 混乱を招く概念であり、使い道がありませんでした。そこで、他の人が混乱している場合に備えて、次のコード スニペットを作成しました:
// 車両が持つことができるさまざまな詳細
$hasFourWheels = 1;
$hasTwoWheels = 2;
$hasDoors = 4;
$hasRedColour = 8;
$bike = $hasTwoWheels;
$golfBuggy = $hasFourWheels;
$ford = $には4つの車輪があります$hasDoors;
$ferrari = $hasFourWheels $ドアあり$は赤い色;
$はBike = $はFourWheels & $bike# $bike には 4 つの車輪がないため、誤りです
$isGolfBuggy = $hasFourWheels & $golfBuggy# 確かに、$golfBuggy には 4 つの車輪があるからです
$isFord = $hasFourWheels & $ford# $ford $hasFourWheels
?>

そして、これを多くのものに適用できます。たとえば、security:
// Security Permissions:
$ writePost = 1;
$readPost = 2;
$deletePost = 4 ;
$addUser = 8 ;
$deleteUser = 16;

// ユーザーグループ:
$administrator = $write投稿$read投稿 $投稿を削除 $addUser $deleteUser;
$moderator = $readPost $投稿を削除$deleteUser;
$writer = $writePost $readPost;
$guest = $readPost;
// 許可をチェックする関数
関数 checkPerミッション($user, $許可) {
if(
$user & $permission) {
return
tru​​e;
} else {
return
false;
}
}
// これですべてを適用します!
if(checkPermission( $administrator, $deleteUser)) {
deleteUser(「いくつか User"); # $administrator が $deleteUser できるため実行されます
}
?>

一度覚えてしまえば、とても便利です!問題を避けるために、各値を 2 の累乗で増やすことを忘れないでください

up

down

6ivoras Gmail ドットコム で?
4年前

追加の好奇心として、 何らかの理由で、演算 (「18」と「32」) の結果は「10」になります。言い換えれば、文字列に対して二項演算子の使用を避けてみてください:)

up

down

10?
10年前

実践的なビット演算子 case :
// この色の赤、緑、青の値を知りたいです :
$color = 0xFEA946 ;
$red = $color >> 16 ;
$green= ($color & 0x00FF00) >> 8 ;
$blue = $color & 0x0000FF ;
printf( 「レッド」 : %X (%d)、緑 : %X (%d)、青 : %X (%d)',
$red, $red, $green$グリーン$ブルー$ブルー) ;
// 表示されます...
// 赤 : FE (254)、緑 : A9 (169)、青 : 46 (70)
?>

up

ダウン

4zooly globmi ドットコム で?
5 年前

これはビットごとの例です leftrotate と rightrotate。
この関数は 10 進数でのみ機能することに注意してください。他の型は Pack() で変換できます。
function rotate ( $decmal, $bits) {
$binary = decbin($10進数);
return (
bindec(substr( $バイナリ$ビット).substr($binary, 0, $bits))
);
}
// 1を回転24 (1111100) を左に1 ビット
echo rotate(124, 1);
// = 121 (1111001)
// 124 回転 (111) 1100) 3ビットで右へ
エコー回転(124, -3);
// = 79 (1001111)
?>

3 ジョシュ joshstrike ドットコム で?
4年前

これをさらに参照するには 何よりも自分自身...長さ $bits のマスクで $n 個のフラグが 1 に設定されているすべての可能なバイナリの組み合わせを反復処理する必要がある場合:
echo masksOf( 310); 
関数
マスクOf($n,$bits) {
$u = pow(2,$bits)-1//スタート 値、フルフラグがオン。 
$マスク = array(); 
その間 (
$u>0) {
$z = numflags($u); 
if (
$z==$n) array_push($masks,$u); 
$u--; 
}
return (
$マスク);    
}
関数
numflags($n) {
$k = 0
while (
$n) {
$k += $n & 1
$n = $n >> 1
}
return (
$k); 
// 代わりに:
// $u = 0; 
// for ($k=1;$k// $u+=($n&$k?1:0); 
// }
// return ($u); 
}
?>

4スペンサー・P・モイ 例のドットコム で?
3 年前

NOT または補数演算子 ( ~ ) と負の 2 進数は混乱を招く可能性があります。
~2 = -3 という公式を使用するためです ~x = -x - 1 10 進数のビット単位の補数は、数値から 1 を引いた値の否定です。
注: を使用するだけです。以下の例では 4 ビットですが、実際には PHP は 32 ビットを使用します。
負の 10 進数 (例: -3) を 2 進数に変換するには 3 つの手順が必要です:
1) 10 進数の正の値を 2 進数 (例: 3) に変換します。 = 0011)
2) ビットを反転します (例: 0011 が 1100 になります)
3) 1 を加算します (例: 1100 + 0001 = 1101)
1101 = -3 がどのように計算されるのか疑問に思われるかもしれません。 PHP は、負の 2 進数をレンダリングするために「2 の補数」というメソッドを使用します。左端のビットが 1 の場合、2 進数は負であるため、ビットを反転して 1 を加算します。0 の場合、それは正であるため、加算しません。 何でもしなければなりません。したがって、0010 は正の 2 になります。1101 の場合は負なので、ビットを反転すると 0010 が得られます。1 を加算すると、-3 に等しい 0011 が得られます。 4

シルバー

?

6ね

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート