知っていて当たり前-08　演算子

# 知っていて当たり前-08　演算子

## 1.　算術演算子

表現 | 名前
:---|:---
`+x` | 単項プラス
`-x` | 単項マイナス
`x + y` | 加算
`x - y` | 減算
`x * y` | 乗算
`x / y` | 除算
`x ÷ y` | 整数除算 `div(x, y)` と等価
`x \ y` | 逆除算 `y/x` と等価
`x ^ y` | べき乗
`x % y` | 余剰 `rem(x, y)` と等価
`!x` | ブール値の否定

### 1.1.　`÷` と `div()` と `fld()`

`÷` と `div()` は表記の違いだけ同じ結果になるが，`fld()` は同じ結果にならない場合がある。


```julia
demo(x, y) = println("$(x ÷ y), $(div(x, y)), $(fld(x, y))")
```




    demo (generic function with 1 method)




```julia
demo(14, 4)
```

    3, 3, 3



```julia
demo(14, -4)
```

    -3, -3, -4



```julia
demo(-14, 4)
```

    -3, -3, -4



```julia
demo(-14, -4)
```

    3, 3, 3


### 1.2.　`%` と `rem()` と `mod()`

`%` と `rem()` は表記の違いだけ同じ結果になるが，`mod()` は同じ結果にならない場合がある。


```julia
demo(x, y) = println("$(x % y), $(rem(x, y)), $(mod(x, y))")
```




    demo (generic function with 1 method)




```julia
demo(14, 4)
```

    2, 2, 2



```julia
demo(14, -4)
```

    2, 2, -2



```julia
demo(-14, 4)
```

    -2, -2, 2



```julia
demo(-14, -4)
```

    -2, -2, -2


### 1.3.　否定


```julia
.~[false, true]
```




    2-element BitVector:
     1
     0




```julia
~false, ~true
```




    (true, false)



## 2.　比較演算子

表現 | 名前
:---|:---
`x == y` | 等しい
`x != y`, `x ≠ y` | 等しくない
`x < y` | 小さい
`x <= y`, `x ≤ y` | 小さいか等しい
`x > y` | 大きい
`x >= y`, `x ≥ y` | 大きいか等しい

## 3.　論理演算子

表現 | 名前
:---|:---|
`x && y` | 論理積（短絡評価）
`x ｜｜ y` | 論理和（短絡評価） 注：左欄の縦棒は全角で表示されているが半角で！
`x & y` | 論理積
`x ｜ y` | 論理和 注：左欄の縦棒は全角で表示されているが半角で！


```julia
4 > 2 && println("これが表示される")
```

    これが表示される



```julia
4 < 2 && println("これは決して表示されない")
```




    false




```julia
4 < 2 || println("これが表示される")
```

    これが表示される



```julia
4 > 2 || println("これは決して表示されない")
```




    true




```julia
true & false
```




    false




```julia
true | false
```




    true



## 4.　ビット演算子

ビット演算は負の整数も対象にできるが，整数のビット表示について詳しい知識がない場合には思いがけない結果になって戸惑うこともあるかも知れない。ビット演算は符号なし整数もしくは正の整数に限定して用いることを推奨する。

表現 | 名前
:---|:---|
`~x` | 否定
`x & y` | 論理積
`x` $|$ `y` | 論理和
`x ⊻ y` | 排他論理和
`x >>>` y | 右シフト（論理）
`x >> y` | 右シフト（算術）
`x << y` | 左シフト

### 4.1.　否定

ビットを反転する（0 を 1 に，1 を 0 に）。

#### 4.1.1.　符号なし 64 ビット整数の場合

10 進数の 3 は，64 ビット 2 進数 UInt64 では 

    0000000000000000000000000000000000000000000000000000000000000011

ビットを反転させると

    1111111111111111111111111111111111111111111111111111111111111100


```julia
UInt64(3)
```




    0x0000000000000003




```julia
~UInt64(3)
```




    0xfffffffffffffffc




```julia
println(~UInt64(3))
```

    18446744073709551612


#### 4.1.2.　符号あり 64 ビット整数の場合



```julia
~Int64(3), ~3 # 3 ≡ Int64(3) である
```




    (-4, -4)




```julia
~(-3)
```




    2



Int64(3) は

    0000000000000000000000000000000000000000000000000000000000000011

反転させると

    1111111111111111111111111111111111111111111111111111111111111100

メモリ内では64ビットがこのようなる。もっとも左端のビットは符号ビットと呼ばれ，これが 1 であるときは負の数を表しているとみなされる。
実際の数値は，まずビットを反転する（もとに戻る）。これを「1 の補数表示」と呼ぶ。

    0000000000000000000000000000000000000000000000000000000000000011

1 を 足す（繰り上げ処理を伴う）。これを「2 の補数表示」と呼ぶ。

    0000000000000000000000000000000000000000000000000000000000000011
    +                                                              1
    ----------------------------------------------------------------
    0000000000000000000000000000000000000000000000000000000000000100

これを 10 進数で表すと $1 \times 2^2 + 0 \times 2^1 + 0 \times 2^0 = 4$

符号ビットが 1 だったので，符号を - にして，-4 が `~Int64(3)` の答えになる。

計算過程は面倒だが，結果は明快である。

x が正の 64 ビット整数の場合，`~x ≡ -x - 1` である

Int64(-3) は

まず，絶対値 3 を 2進 64 桁で表わす。上位桁は　0 で埋める。

    0000000000000000000000000000000000000000000000000000000000000011

反転する。

    1111111111111111111111111111111111111111111111111111111111111100

1 を足す（繰り上がり処理を伴う。

    1111111111111111111111111111111111111111111111111111111111111101

とにもかくにも，

Int64(-3) は

    111111111111111111111111111111111111111111111111111111111111101

~Int64(-3) を求めるにはビット反転を行う。

    000000000000000000000000000000000000000000000000000000000000010

これは 10 進数の 2 である。これが `~Int64(-3)` の答えである。

計算過程は面倒だが，結果は明快である。

x が負の 64 ビット整数の場合，`~x ≡ -x - 1` である。

結局，x が正であろうが負であろうが `~x ≡ -x - 1` である。


```julia
x = Int64(-56785678678)
~x, -x - 1
```




    (56785678677, 56785678677)




```julia
x = Int64(5656786784546)
~x, -x - 1
```




    (-5656786784547, -5656786784547)



### 4.2.　論理積


```julia
[false, true] .& [false, true]'
```




    2×2 BitMatrix:
     0  0
     0  1




```julia
false & false, false & true, true & false, true & true
```




    (false, false, false, true)



### 4.3.　論理和


```julia
[false, true] .| [false, true]'
```




    2×2 BitMatrix:
     0  1
     1  1




```julia
false | false, false | true, true | false, true | true
```




    (false, true, true, true)



### 4.4.　排他論理和


```julia
[false, true] .⊻ [false, true]'
```




    2×2 BitMatrix:
     0  1
     1  0




```julia
false ⊻ false, false ⊻ true, true ⊻ false, true ⊻ true
```




    (false, true, true, false)




```julia
xor(false, false), xor(false, true), xor(true, false), xor(true, true)
```




    (false, true, true, false)



### 4.5.　右シフト（論理）


```julia
string(UInt8(100), base=2)
```




    "1100100"



8 ビット符号なし整数 100 は，16 進数表示で 0b1100100
右に 1 ビットシフトすると 0b0110010 となる。16 進数表示では 0x32，10 進数表示では 50 である。
論理右シフトでは右端（最下位桁）は失われ，左端（最上位桁）には 0 が補われる。


```julia
Int8(100) >>> 1
```




    50



8 ビット符号付整数 -100 は，16 進数表示で 0b11100100
左端の 1 は符号ビットで，1 のときに負の数であることを示す。
右に 1 ビットシフトすると 11110010


```julia
Int8(-100) >>> 1
```




    78




```julia
string(UInt(9223372036854775758), base=16)
```




    "7fffffffffffffce"




```julia
string(100, base=16)
```




    "64"




```julia
0x64 >>> 1
```




    0x32




```julia
string(-100, base=16)
```




    "-64"




```julia
-0x64 >>> 1
```




    0x4e



### 4.6.　右シフト（算術）


```julia
 100 >> 1
```




    50




```julia
-100 >> 1
```




    -50



### 4.7.　左シフト


```julia
 100 <<  1
```




    200




```julia
-100 <<  1
```




    -200



## 5.　代入演算子

表現 | 名前
:---|:---
`=` | 代入
`+=` | 加算代入
`-=` | 減算代入
`*=` | 乗算代入
`/=` | 除算代入
`÷=` | 整数除算代入
`\=` | 逆除算代入
`%=` | 剰余代入
`^=` | べき乗代入
`&=` | ビット論理積代入
`｜=` | ビット論理和代入 注：左欄の縦棒は全角で表示されているが半角で！
`⊻=` | ビット排他論理和代入
`>>>=` | 右論理シフト代入
`>>=` | 右算術シフト代入
`<<=` | 左シフト代入



```julia
x = 5
x += 1
```




    6




```julia
x = 5
x = x + 1
```




    6




```julia
x = 5
x *= x + 1 
```




    30




```julia
x = 5
x = x * (x + 1) # x * x + 1 ではない
```




    30