ブール演算子とビット演算子のどちらを使用すべきかについて混乱しています
and
vs &
or
vs |
誰かがそれぞれをいつ使用し、いつ他のものを使用すると結果に影響するかについて私に啓発できますか?
ガイドラインは次のとおりです。
短絡動作は、次のような式で役立ちます。
if x is not None and x.foo == 42:
# ...
これは、両側が常に評価され、&
を与えるため、ビット単位のAttributeError: 'NoneType' object has no attribute 'foo'
演算子では正しく機能しません。ブール値のand
operatorを使用すると、最初の式がFalseの場合、2番目の式は評価されません。同様に、or
は、最初の引数がTrueの場合、2番目の引数を評価しません。
理論的には、and
およびor
はブールロジックから直接派生します(したがって、2つのブールを操作してブールを生成します)が、_&
_および_|
_はブールおよび/または整数の個々のビットに適用されます。ここでは、後者が正確に機能する方法について多くの質問があります。
結果に影響を及ぼす可能性のある実際的な違いを次に示します。
and
とor
の短絡、つまりTrue or sys.exit(1)
は終了しません。これは、最初のオペランドの特定の値(_True or ...
_、_False and ...
_)に対して、2番目のオペランドが変更されないためですresult =を評価する必要はありません。しかし、_|
_と_&
_は短絡しません-True | sys.exit(1)
はREPLから抜け出します。&
_および_|
_は通常の演算子であり、オーバーロードできます-and
およびor
は言語に偽造されます(少なくともPythonでは、ブールへの強制のための特別な方法には副作用があります)。and
およびor
は、(常にこれを本当に理解することも、必要とすることもありません)True
またはFalse
の代わりにオペランドの値を返します。これは条件内のブール式の意味を変更しません-_1 or True
_は_1
_ですが、_1
_もtrueです。しかし、かつて条件演算子をエミュレートするために使用されていました(C構文の_cond ? true_val : false_val
_、Python数年前から)_true_val if cond else false_val
_。_&
_および_|
_、結果の型は、オペランドがそれぞれの特別なメソッドをオーバーロードする方法に依存します(_True & False
_はFalse
、_99 & 7
_は_3
_で、集合の和集合/交差点については...)。しかし、たとえ_a_boolean & another_boolean
_は同じように機能しますが、正しい解決策はand
を使用することです-単にand
とor
がブール式と条件に関連付けられているのに対し、_&
_と_|
_はビット調整を表します。
ここにさらなる違いがありますが、今しばらく困惑していました:_&
_(および他のビット演算子)はand
(および他のブール演算子)より高い優先順位を持っているため、次の式は異なると評価されます値:
_0 < 1 & 0 < 2
_
versus
_0 < 1 and 0 < 2
_
つまり、最初のFalse
は0 < (1 & 0) < 2
と同等であり、したがって_0 < 0 < 2
_、したがって_0 < 0 and 0 < 2
_になります。
numpy
で要素単位のブール演算を実行しようとしている場合、答えは多少異なります。要素単位のブール演算には&
と|
を使用できますが、and
とor
は値エラーを返します。
安全のために、 numpy logic functions を使用できます。
np.array([True, False, True]) | np.array([True, False, False])
# array([ True, False, True], dtype=bool)
np.array([True, False, True]) or np.array([True, False, False])
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
np.logical_or(np.array([True, False, True]), np.array([True, False, False]))
# array([ True, False, True], dtype=bool)
ブール演算は論理演算です。
ビット演算は、バイナリビットの演算です。
ビット演算:
>>> k = 1
>>> z = 3
>>> k & z
1
>>> k | z
3
操作:
And & 1 if both bits are 1, 0 otherwise
Or | 1 if either bit is 1
Xor ^ 1 if the bits are different, 0 if they're the same
Not ~ Flip each bit
ビット演算の使用法のいくつか:
1)ビットの設定とクリア
ブール演算:
>>> k = True
>>> z = False
>>> k & z # and
False
>>> k | z # or
True
>>>
ヒントは名前にあります:
ビット効率演算子を使用して論理演算を実行することは可能ですが、実際には(通常は効率上の理由で)望ましい場合もありますが、微妙なバグや望ましくない副作用を防ぐために、一般的にそのような目的でそれらを回避する必要があります。
ビットを操作する必要がある場合、ビットごとの演算子は専用です。楽しい本: Hackers Delight には、ビットトゥイドリングで達成できることのクールで真に有用な例が含まれています。
一般的な規則は、既存のオペランドに適切な演算子を使用することです。ブールオペランドでブール(論理)演算子を使用し、(より広い)整数オペランドでビット単位演算子を使用します(注:Falseはと同等、およびTrueから1)。唯一の「つまらない」シナリオは、ブール演算子を非ブールオペランドに適用することです。
[SO]:Python-'and'と '&'の違い[duplicate] :5 & 7
で説明されている簡単な例を見てみましょう。 vs。5 and 7
。
bitwiseand(&)の場合、物事は簡単です。
5 = 0b101 7 = 0b111 ----------------- 5 & 7 = 0b101 = 5
論理andの場合、次のようになります [Python 3]:ブール演算 状態(emphasisは私の):
( and も or も値とタイプを制限しないことに注意してくださいFalseとTrueではなく、最後に評価された引数を返す。
Example:
>>> 5 and 7 7 >>> 7 and 5 5
もちろん、vs。orにも同じことが当てはまります。
ブール値の「and」とビット単位の「&」:
擬似コード/ Pythonは、これらの違いを理解するのに役立ちました。
def boolAnd(A, B):
# boolean 'and' returns either A or B
if A == False:
return A
else:
return B
def bitwiseAnd(A , B):
# binary representation (e.g. 9 is '1001', 1 is '0001', etc.)
binA = binary(A)
binB = binary(B)
# perform boolean 'and' on each pair of binaries in (A, B)
# then return the result:
# equivalent to: return ''.join([x*y for (x,y) in Zip(binA, binB)])
# assuming binA and binB are the same length
result = []
for i in range(len(binA)):
compar = boolAnd(binA[i], binB[i])
result.append(compar)
# we want to return a string of 1s and 0s, not a list
return ''.join(result)
論理演算
通常、条件文に使用されます。例えば:
if a==2 and b >10 then /*Do something...*/ endif
これは、両方の条件((a == 2)(b> 10))が同時に真である場合、条件文の本体を実行できることを意味します。
ビット演算
ビット操作は、データの操作と抽出に使用できます。たとえば、整数の4つのLSB(最下位ビット)を抽出する場合は、次の操作を実行できます。
抽出:
poo & 0x000F
マスキング:
poo | 0xFFF0