82171


Pythonで`&`と`>>`はどのような意味でしょうか。  
うまくWeb検索できないのでご教示ください。

`&`が積(intersection)を求める[集合演算子](https://qiita.com/Tocyuki/items/0bc783daab382ef7a0ec#%E7%A9%8Dintersection)であることは分かっています。  
しかし以下のコードには当てはまらないように見えます：

[code]

    def numberOfSteps (self, num: int) -> int:
        stepCount = 0 if num else 1
        while num:
            stepCount += (num & 1) + 1
            num >>= 1
        return stepCount - 1
    
[/code]

* * *

この質問は[¿Qué significan los símbolos "&" y ">>" en
Python?](https://es.stackoverflow.com/q/453092)を和訳したものです。


CC BY-SA 4.0
2021-09-02T00:57:22.427
82170
2021-09-02T12:30:45.760
2021-09-02T12:27:37.930
9820
47532
question
python
Pythonのシンボル「&」と「>>」とはどういう意味ですか?


# ビット演算子

ビット演算子は、数値をビット(0と1)で計算する[ビット演算](https://qiita.com/7shi/items/41d262ca11ea16d85abc)と呼ばれる処理に使用されます。

# オペレーター `>>` (bitwise right shift)

`>>`演算子は **右シフト** または **right shift(rshift)** と呼ばれ、n ビットの右シフトを示します。  
例：

[code]

    a = 60            #0011 1100 
    b = 13            #0000 1101 
    
    #もし >> 2 を実行した場合は2ビット分(2進数で2桁分)右に動きます
    r = a >> 2
    #r = 0000 1111
    print(r) #15
    
[/code]

右シフトと`num/pow(2,n)`が同一の処理に見えますが、それは間違いです。  
右シフトの結果は整数を返しますが、除算は小数を返すことがあります。  
例：

[code]

    #operator
    60 >> 2
    #15
    
    #formula
    60/pow(2,2)
    #15
    
    #again
    60 >> 3
    #7
    
    60/pow(2,3)
    #7.5
    
[/code]

後者(#again)の場合は、ビット演算と除算で異なる結果になります。  
整数で除算するには`int(60/pow(2,3))`のようにintへキャストする方法があります。  
また、`60//pow(2,3)`のように商の整数部分を返す切り捨て除算`//`を使用する方法もあります。

# オペレーター `&` (bitwise and)

最初に述べたようにビット演算はビット単位であるため、真偽値(True/False)で使用されるので and 演算子と同じ意味にはなりません。  
また、`&`で実行される操作はデータ型によって異なりますが、この演算子の興味深い点は、呼び出す関数を `__and__` と `__rand__`
として再定義できることです。

この場合、`&`演算子は[set（集合）型](https://docs.python.org/ja/3/library/stdtypes.html#set-
types-set-frozenset)の操作と同様にふるまいますが、ビット演算と同じように数字が両方とも 1 ならば 1 を、それ以外の場合は 0
を返します。  
例：

[code]

    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
    
[/code]

この結果、出力は10進数で 12 を表すビット(2進数) 0000 1100 になります。

# ご質問のコード

ご質問のコードでは、`stepCount = 0 if num else 1`の行で引数`num`が`True`か`False`かを判定します。  
任意の数または空でない文字列である場合は `True` になります。0 または空文字(`""`)の場合は`False`となり、`True`の場合は 0
を、`False`の場合は 1 を割り当てます。(cf:
[三項演算子](https://qiita.com/howmuch515/items/bf6d21f603d9736fb4a5))  
その後、`num & 1`で1(ビット単位)との積を求め、続いて`while`ループに移動します。

[code]

    # 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を引いた値を返します
    
[/code]

`num`が `0000 0000` になるまで右シフトを繰り返し、累積された値を返します。


CC BY-SA 4.0
2021-09-02T00:57:22.427
82171
2021-09-02T12:30:45.760
2021-09-02T12:30:45.760
9820
47532
82170
answer