以下は、PHP のシフト操作とシフト操作に関する一般的に使用される学習メモです。この記事がすべての学生にとって有益であることを願っています。
ビット演算アプリケーションのヒント
ビットをクリアするには、AND を使用します。特定の位置が使用可能であるか、または
否定して交換したい場合は、XORを使用すると簡単です
シフト操作
ポイント1 どちらも二項演算子で、演算部品は両方とも整数で、結果も整数になります。
2「<<」 左シフト:右側の空いているビットを0で埋めると、左側のビットが単語の先頭から絞り出され、その値は2倍に相当します。
3 ">>"右シフト: 右側のビットが絞り出されます。左から繰り出された空きビットは、正の数の場合は 0 で埋められます。負の数の場合は、使用するコンピュータ システムに応じて 0 または 1 で埋められます。
4 ">>>" 演算子では、右側のビットが絞り出され、左側にシフトされた空いた部分はすべて 0 で埋められます。
ビット演算子の適用 (ソースオペランドのマスクマスク)
(1) ビット単位の AND-- &
1 特定のビットをクリアします (マスク内の特定のビットは 0、他のビットは 1、s=s&mask)
2 特定の数値内の指定されたビットを取得します (マスク内の特定の位置は 1、他のビットは 0、s=s&mask)
(2) ビット単位の OR-- |
ソース オペランドの特定のビットを 1 に設定し、他のビットは変更しないままにするためによく使用されます。 (マスク内の特定の位置は 1、他のビットは 0 s=s|mask)
(3) ビット XOR-- ^
1 は特定のビットの値を反転します (マスク内の特定の位置は 1、他のビットは 0 s=s^mask)
2 3番目の変数を導入せず、2つの変数の値を交換します(a=a1,b=b1と仮定します)
運用後の目標運用状況
a=a1^b1 a=a^b a=a1^b1,b=b1
b=a1^b1^b1 b=a^b a=a1^b1,b=a1
a=b1^a1^a1 a=a^b a=b1,b=a1
2の補数の算術公式:
-x = ~x + 1 = ~(x-1)
~x = -x-1
-(~x) = x+1
~(-x) = x-1
x+y = x - ~y - 1 = (x|y)+(x&y)
x-y = x + ~y + 1 = (x|~y)-(~x&y)
x^y = (x|y)-(x&y)
x|y = (x&~y)+y
x&y = (~x|y)-~x
x==y: ~(x-y|y-x)
x!=y: x-y|y-x
x x
x< y: (~x&y)|((~x|y)&(x-y))//符号なし x,y 比較 x<=y: (~x|y)&((x^y)|~(y-x))//符号なし x,y 比較 応用例 (1) int型変数aが奇数か偶数かを判定します a&1 = 0 偶数 a&1 = 1 の奇数 (2) int型変数aのk番目のビット(k=0,1,2...sizeof(int))、つまりa>>k&1を取り出します (3) int型変数aのkビット目を0、つまりa=a&~(1
(4) int型変数aのk番目の位置を1、つまりa=a|(1
(5) int型変数を左にk回循環シフト、つまりa=a16-k(sizeof(int)=16と仮定) (6) int型変数aをk回右に巡回シフトする、つまりa=a>>k|a
(7)整数の平均 2 つの整数 x と y について、(x+y)/2 を使用して平均を計算すると、x+y が INT_MAX より大きい可能性があるため、オーバーフローが発生しますが、それらの平均は絶対にオーバーフローしないことがわかっています。次のアルゴリズム: int Average(int x, int y) //X、Yの平均を返します { return (x&y)+((x^y)>>1); } (8) 整数が 2 のべき乗であるかどうかを判断します。数値 x >= 0 の場合、それが 2 のべき乗であるかどうかを判断します ブール値 power2(int x) { リターン ((x&(x-1))==0)&&(x!=0); } (9) 温度なしで 2 つの整数を交換します void swap(int x , int y) { x ^= y; y ^= x; x ^= y; } (10)絶対値を計算する int abs(int x) { いや; y = x > 31 ; return (x^y)-y ; //または: (x+y)^y } (11) モジュロ演算をビット演算に変換(オーバーフローなし) % (2^n) は & (2^n - 1) と同等です (12) 乗算演算はビット演算に変換されます(オーバーフローなし) a * (2^n) は a
(13) 除算演算をビット演算に変換します(オーバーフローなし) a / (2^n) は a>> n と同等です
と同等
最後にバイナリシフト演算に関する情報を追加します
PHP は主にテキスト演算を目的として設計されており、実際には数学演算には適しておらず、効率も高くありません。しかし、このプロジェクトではバイナリ ディスプレイスメント演算を使用する必要があるため、PHP でいくつかの問題が発生しました。
>>0xFFFFFFFF
32 ビットの符号付き整数では、0xFFFFFFFF は -1 を表す必要があります:
>> (int)0xFFFFFFFFFF
PHP は浮動小数点数の 2 進シフト演算をサポートしていません。これを実行する場合は、最初に整数に変換され、最終結果も整数として返されます。
4294967295
>> タイプを取得(0xFFFFFFFF)
「ダブル」
-1
>> 1
1073741824
>> 1
1
>>>>> 1
;
-1
>> 1 <<
1
>>>>> 1
>>>>> 2
;
-1
>>>>>3
;
-1
>>>>>31
-1
この問題を解決するには、BCMath 数学関数ライブラリを使用して、文字列や GMP/BigInt 拡張などで表される整数を直接処理することを検討しました。しかし、文字列を使用しているので、文字列をより徹底的に扱い、数値を 32 個のバイナリ文字列に変換し、手動で 0 を埋め、最後にそれらを元に戻すことができると思います。
コードは次のとおりです:
(さらに、コードは実際には任意のバイナリ ビット シフト演算に拡張できますが、ここでは実行しませんでした)
PHP
コードは次のとおりです | コードをコピー |
/** * 符号なし 32 ビット右シフト * @parammixed $x 演算対象の数値。文字列の場合は 10 進数形式でなければなりません * @param string $bits 右シフト数値 * @return 混合結果、整数の範囲を超える場合は浮動小数点数を返します */ 関数 shr32($x, $bits){ //変位が範囲を超える 2 つの状況 If($bits $x を返します; } If($bits >= 32){ 0 を返す; } //2進数を表す文字列に変換します $bin = decbin($x); $l = strlen($bin); //文字列の長さが超える場合は下位32ビットが切り取られ、長さが足りない場合は上位ビットが0~32ビットで埋められます If($l > 32){ $bin = substr($bin, $l - 32, 32); }elseif($l $bin = str_pad($bin, 32, '0', STR_PAD_LEFT); } // 移動する桁数を取得し、左側に 0 を埋め込みます 戻り値bindec(str_pad(substr($bin, 0, 32 - $bits), 32, '0', STR_PAD_LEFT)); } /** * 符号なし 32 ビット左シフト * @parammixed $x 演算対象の数値。文字列の場合は 10 進数形式でなければなりません * @param string $bits 左シフト数値 * @return 混合結果、整数の範囲を超える場合は浮動小数点数を返します */ 関数 shl32 ($x, $bits){ //変位が範囲を超える 2 つの状況 If($bits $x を返します。 } If($bits >= 32){ 0 を返します。 } //2進数を表す文字列に変換します $bin = decbin($x); $l = strlen($bin); //文字列の長さが超える場合は下位32ビットが切り取られ、長さが足りない場合は上位ビットが0~32ビットで埋められます If($l > 32){ $bin = substr($bin, $l - 32, 32); }elseif($l $bin = str_pad($bin, 32, '0', STR_PAD_LEFT); } //移動する桁数を取得し、右側に0 を入力します 戻り値bindec(str_pad(substr($bin, $bits), 32, '0', STR_PAD_RIGHT)); } |
http://www.bkjia.com/PHPjc/632618.html
。