web-dev-qa-db-ja.com

PHP&(アンパサンド、ビットごと))演算子を理解する

私はコードで($var & 1)をよく使用しています。$varが奇数の場合はtrueを返し、偶数の場合はfalseを返します。

しかし、「&」は実際には何をするのでしょうか。

57

&はバイナリandです。バイナリ値があり、別のバイナリ値をandしている場合、結果は2つの値のビット単位のandになります。例:

  01101010
& 01011001
= 01001000

右端のビットは1(その場合、数値は奇数)または0で、その場合、数値は偶数です。もし、あんたが & 1の数値では、最下位ビットのみを確認し、ifは数値が1または0かどうかを確認します。他の人が述べたように、ビット演算子は、それらがどのように機能するかについて調べます。

59
Marius

バイナリシステムの基本となる2つの演算は、ORおよびANDです。

ORは、「AがオンまたはBがオンの場合」を意味します。実際の例では、2つのスイッチを並列に接続します。どちらかが電流を通過させている場合、電流は通過します。

ANDは、「AとBの両方がオンの場合」を意味します。実際の例では、2つのスイッチが直列に接続されています。両方が電流を許可している場合のみ、電流が通過します。

コンピュータでは、これらは物理的なスイッチではなく半導体であり、その機能は 論理ゲート と呼ばれます。彼らはスイッチと同じようなことをします-電流に反応するか、電流がないかに反応します。

整数に適用すると、1つの数値のすべてのビットが他の数値のすべてのビットと結合されます。したがって、ビット演算子ORおよびANDを理解するには、数値を2進数に変換してから、一致するビットのすべてのペアに対してORまたはAND演算を実行する必要があります。 。

それが理由です:

_00011011 (odd number)
AND
00000001 (& 1)
== 
00000001 (results in 1)
_

一方

_00011010 (even number)
AND
00000001 (& 1)
==
00000000 (results in 0)
_

したがって、(&1)演算は、ANDロジックを使用して、右端のビットを1と比較します。他のすべてのビットは事実上無視されます。 2進数の偶数は、10進表記の偶数でもあります(10は2の倍数です)。

バイナリシステムの他の基本的な演算には、NOTとXORがあります。 NOTは、「Aがオフの場合」を意味し、2つではなく1つの信号または「パラメータ」のみを取る論理ゲートの唯一の形式です。 XORは、「AまたはBのいずれかがオンで、両方がオンでない場合」を意味します。次に、NAND、NOR、およびNXORがあり、これらは基本的にAND、OR、およびXORと組み合わされていません。つまり、NANDは「AとBが両方ともない場合」を意味します。

プログラミングでは、オペレーターは

_& means AND,
| means OR, 
~ means NOT, and
^ means XOR.
_

その他は、これらを組み合わせることで構成できます。次に例を示します。

_~ (a & b) is equivalent to a NAND operation
_

PHP固有の注意事項

ビット演算子は浮動小数点値では機能せず、PHP=では浮動小数点値が最初に暗黙的に整数に変換されます。整数として表現できる範囲外の数値はゼロに切り捨てられます-そのつまり、PHP_INT_MAXを超えるすべての数値は、式_($num & 1)_)で「偶数」に見えます。 PHP_INT_MIN/PHP_INT_MAX以外の数値をサポートする場合は、fmod($num, 2)が必要です。 ただし、64ビットを使用している場合PHP整数は浮動小数点よりも精度が高くなります。

26
thomasrutter

これは、ビットワイズとPHPについて知っておくのも興味深いです。

/**
 * Regular
 */
echo (true && true); // 1
echo (true && false); // nothing

echo (true || false); // 1
echo (false || false); // nothing

echo (true xor false); // 1
echo (false xor false); // nothing

/**
 * Bitwise
 */
echo (true & true); // 1
echo (true & false); // 0

echo (true | false); // 1
echo (false | false); // 0

echo (true ^ false); // 1
echo (false ^ false); // 0
18
Ólafur Waage

他の回答に加えて、それは注目に値します

_if(func1() && func2())
_

func2()がtrue(「遅延評価」)を返した場合にのみfunc1()を呼び出しますが、

_if(func1() & func2())
_

関係なく両方の関数を呼び出しますが、両方の真理値表は同じです(ブール値を返すと仮定)。


thomasrutterは(以下のコメントで)実際には後者を実行すべきではないと指摘しています。 _(A & B)_は、特に_AおよびBが整数である場合、必ずしも_(A && B)_と同じ真実性を持つとは限りません。たとえば、A = 1およびB = 2(両方とも真実)の場合、A&Bは偽であり、A && Bは真実です。また、別の開発者は、これをタイプミスであると考え、2つのアンパサンドに「修正」する場合があります。

13
mpen

私はあなたの質問がビットごとの演算子を理解することに関するものであることを知っています、そして受け入れられた答えはそれをうまく説明しています。しかし、あなたが与える例では、代わりにモジュロ演算子を使用することをお勧めします:

($var % 2) /* instead of */ ($var & 1)

これは、数が奇数(2で割り切れない)であることを確認していることを明確に示しており、より一般的であるため、同じ方法で($ var%3)を使用して、Nに対してどのように機能するかを推測できます。

12
Pat