質問: 0 if num else 1 while num: stepCount += (num & 1) + 1 num >>= 1 return stepCount - 1 ``` --- この質問は¿Qué significan los símbolos "&" y ">>" en Python?を和訳したものです。
回答: ビット演算子 ====== ビット演算子は、数値をビット(0と1)で計算するビット演算と呼ばれる処理に使用されます。 オペレーター `>>` (bitwise right shift) ================================= `>>`演算子は **右シフト** または **right shift(rshift)** と呼ばれ、n ビットの右シフトを示します。 例: ``` a = 60 #0011 1100 b = 13 #0000 1101 #もし >> 2 を実行した場合は2ビット分(2進数で2桁分)右に動きます r = a >> 2 #r = 0000 1111 print(r) #15 ``` 右シフトと`num/pow(2,n)`が同一の処理に見えますが、それは間違いです。 右シフトの結果は整数を返しますが、除算は小数を返すことがあります。 例: ``` #operator 60 >> 2 #15 #formula 60/pow(2,2) #15 #again 60 >> 3 #7 60/pow(2,3) #7.5 ``` 後者(#again)の場合は、ビット演算と除算で異なる結果になります。 整数で除算するには`int(60/pow(2,3))`のようにintへキャストする方法があります。 また、`60//pow(2,3)`のように商の整数部分を返す切り捨て除算`//`を使用する方法もあります。 オペレーター `&` (bitwise and) ======================== 最初に述べたようにビット演算はビット単位であるため、真偽値(True/False)で使用されるので and 演算子と同じ意味にはなりません。 また、`&`で実行される操作はデータ型によって異なりますが、この演算子の興味深い点は、呼び出す関数を `__and__` と `__rand__` として再定義できることです。 この場合、`&`演算子はset(集合)型の操作と同様にふるまいますが、ビット演算と同じように数字が両方とも 1 ならば 1 を、それ以外の場合は 0 を返します。 例: ``` a = 60 #0011 1100 b = 13 #0000 1101 r = a & b #calculamos la interseccion entre 0011 1100 y 0000 1101 #0011 1100 #0000 1101 #interseccion -> 0000 1100 print(r) #12 ``` この結果、出力は10進数で 12 を表すビット(2進数) 0000 1100 になります。 ご質問のコード ======= ご質問のコードでは、`stepCount = 0 if num else 1`の行で引数`num`が`True`か`False`かを判定します。 任意の数または空でない文字列である場合は `True` になります。0 または空文字(`""`)の場合は`False`となり、`True`の場合は 0 を、`False`の場合は 1 を割り当てます。(cf: 三項演算子) その後、`num & 1`で1(ビット単位)との積を求め、続いて`while`ループに移動します。 ``` # num = 7 と仮定します # if num の結果は True なので stepCount = 0 が代入されます while num: stepCount += (num & 1) + 1 # (7と1の積)に1を足した値を加算します # つまり 0 += (1) +1 = 2 となります num >>= 1 # 1ビット右シフトします # 今回は3が返ります (0d7 = 0b111 → 0b11 = 0d3) ※0dは10進数、0bは2進数を示す # このループは num == 0 になるまで繰り返します return stepCount - 1 # 上記の合計値から1を引いた値を返します ``` `num`が `0000 0000` になるまで右シフトを繰り返し、累積された値を返します。