Pythonの数値型

# 概要
[はじめてのPython第3版](https://www.oreilly.co.jp/books/9784873113937/)の勉強メモ

# アジェンダ
- 数値
- Pythonの式と演算子
- 数値と使用例
- その他の数値型

# Pythonの数値型
## 数値
### 数値リテラル
| リテラルの例 | 型 |
|:--|:--|
| 1234, -24, 0 | 短整数（CのLongに相当） |
| 99999999999999999999L | 長整数 |
| 1.23, 3.14e-10, 4E210, 4.90+210 | 浮動小数点数（Cのdoubleに相当） |
| 0177, 0x9ff, 0XFF | 8進数または16進数（整数） |
| 3+4j, 3.0+4.0j, 3J | 複素数 |

#### **整数、浮動小数点数のサイズと精度**
- Pythonの通常の整数は、Cのlongに相当
- 浮動小数点数はCのdoubleに相当
- 精度はPythonインタプリタの作成に使用されているCコンパイラでlong、doubleにどの程度の精度が与えられているかによって決まる

#### **長整数**
- 整数のリテラルにlあるいはLを付けると長整数になる
- 精度を無限に上げることができるようになる
- 現在のバージョンではLをつける意味はほとんどない

#### **16進数と8進数**
- 8 進整数は、**先頭にゼロ（0）を付け、その後に0 ～ 7の範囲の数字**を書く
- 16進数は、**先頭に0xを付け、その後に0 ～ 9の範囲の数字、あるいはA ～ Fの範囲の文字**（大文字、小文字どちらでもよい）を書く

#### **複素数**
- 複素数を実数部+虚数部という形式で書く
- 虚数部の最後には、jあるいはJを付ける
- 実数部はない場合もあり、また虚数部を実数部より先に書くこともできる
- 複素数は、システム内部では浮動小数点数のペアとして扱われるが、複素数を利用した演算は正しく行われる

### ビルトインツールとエクステンション
#### **演算子**
- `+`, `*`, `>>`, `**` など

#### **数学関数（ビルトイン関数）**
- `pow`, `abs` など

#### **ユーティリティモジュール**
- `random`, `math` など

#### **本格的な数値計**
- NumPy（Numeric Python）
  - matrixなどのデータ型や、高度な演算処理のためのライブラリが用意されている
  - 詳細はVaults of Parnassus などのサイトで知ることができる


## Pythonの式と演算子
### PYthonの演算子
| 演算子 | 説明 |
|:-:|:--|
| yield x | ジェネレータ関数を定義する際に使用 |
| lambda 引数: 式 | 無名関数の作成に使用 |
| x if y else z | 三項演算子 |
| x or y | 論理和 |
| x and y | 論理積 |
| not x | 論理否定 |
| x < y<br>x <= y<br>x > y<br>x >= y | 比較演算子 |
| x == y<br>x <> y<br>x != y | 値の同等性比較演算子 |
| x is y<br>x is not y | オブジェクト比較演算子 |
| x in y<br>x not in y | シーケンスのメンバであるかを確認する演算子 |
| x &#x7C; y | ビット論理和 |
| x ^ y | ビット排他的論理和 |
| x & y | ビット論理積 |
| x << y<br>x >> y | シフト演算子 |
| -x + y<br>x - y | 加算/連結<br>減算 |
| x * y<br>x % y<br>x / y<br>x // y | 乗算/繰り返し<br>剰余/文字列フォーマット<br>除算 |
| -x<br>+x<br>~x<br>x ** y | 符号を反転させる（させない）<br>ビットの反転<br>べき乗 |
| x[ i ]<br>x[ i : j ]<br>x.attr<br>x(...) | インデクシング<br>スライシング<br>属性の参照<br>関数呼び出し |
| (...)<br>[...]<br>{...}<br>'...' | タプル<br>リスト<br>ディクショナリ<br>文字列への変換 |

### 演算子の組み合わせ（優先順位）
- 明示的に示すのが吉
- 優先度を明確にするにはカッコを使う

```pycon
>>> (x + y) * z

>>> x + (y * z)
```

### 式中での型の混在
- 複数の型が 1 つの式に混在している場合、Python ではまず、オペランドの型の変換が行われる
- すべてのオペランドの型が、使用されている型の中で最も「複雑」なものに揃えられる
- 短整数の値が大きくなりすぎた場合に自動的に長整数に変換するということも行われる
- 型の自動変換は数値型の値でのみ行われる
- Python では、型の「複雑さ」に関してあらかじめランク付けがされている

| ランク | 型 |
|:-:|:-:|
| 1 | 複素数 |
| 2 | 浮動小数点数 |
| 3 | 長整数 |
| 4 | 短整数 |


### 演算子のオーバーロード
- 演算子はPythonのクラスやCのエクステンションによってオーバーロードされる(または新たに作られる)ことがある
- この特性は一般にポリモーフィズムと呼ばれる
  - 「処理対象となるオブジェクトの型によって機能が変わる」

## 数値と使用例
### 数値の表現
- `print`ステートメントを使わなかった場合に表示された値は、ハードウェアの導き出した答えがそのまま出力されたものである

### ビット演算
```pycon
# xの値が0001に
>>> x = 1
>>> x << 2
4

# 左に2ビットシフトして0100に
>>> x | 2
3

# OR演算で0011に # AND演算で0001に
>>> x & 1
1
```

### 長整数
- 数値の最後にアルファベットのL(小文字のlでもよい)を付けると、長整数であるとみなされる
- メモリ容量の許す限り、いくらでもサイズ(桁数)を増やせるという特徴がある

### 複素数
- Pythonでは2つの浮動小数点数を使って表現される
- 一方は実数部、もう一方は虚数部に対応する
- 数値が虚数部のものであることを示すには、J(小文字のjでもよい)を末尾に付け、実数部と虚数部を組み 合わせるには+を使用する

```pycon
>>> 1j * 1J
(-1+0j)
>>> 2 + 1j * 3
(2+3j)
>>> (2+1j)*3
(6+3j)
```

### 16進数と8進数
- 8進数は先頭を0にし、その後に0~7の数字を並べる。個々の桁は3ビットに相当する。
- 16進数は先頭を0xあるいは0Xにし、その後に0~9の数字かA~Fのアルファベット(小文字でもよい)を並べる。個々の桁は4ビットに相当する。
- 8進数や16進数で表現されていても、整数は整数であることに変わりはない
- Python の場合、整数はデフォルトでは 10 進数で出力される
- ビルトイン関数の中には、 10 進数を 8 進数、16 進数に変換するものもある
- 8 進数や 16 進数を10進数に変換できる`int`という関数もある
- 文字列フォーマットの式を使用することによって 10 進数を 8 進数、16 進数に変換 することも可能

```pycon
# 8進数
>>> 01, 010, 0100
(1, 8, 64)

# 16進数
>>> 0x01, 0x10, 0xFF
(1, 16, 255)

>>> oct(64), hex(64), hex(255)
('0100', '0x40', '0xff')

>>> int('0100'), int('0100', 8), int('0x40', 16)
(100, 64, 64)

>>> eval('100'), eval('0100'), eval('0x40')
(100, 64, 64)

>>> "%o %x %X" % (64, 64, 255)
'100 40 FF'
```

### 数値処理のためのビルトインツール
```pycon:mathモジュール
>>> import math

# よく使用される定数
>>> math.pi, math.e
(3.1415926535897931, 2.7182818284590451)

# サイン、コサイン、タンジェント
>>> math.sin(2 * math.pi / 180)
0.034899496702500969

# 平方根
>>> math.sqrt(144), math.sqrt(2)
(12.0, 1.4142135623730951)


>>> abs(-42), 2**4, pow(2, 4)
(42, 16, 16)

# 切り捨て、丸め
>>> int(2.567), round(2.567), round(2.567, 2)
(2, 3.0, 2.5699999999999998)
```

```pycon:randomモジュール
>>> import random
>>> random.random()
0.49741978338014803

>>> random.random()
0.49354866439625611

>>> random.randint(1, 10)
5

>>> random.randint(1, 10)
4

>>> random.choice(['Life of Brian', 'Holy Grail', 'Meaning of Life'])
'Life of Brian'

>>> random.choice(['Life of Brian', 'Holy Grail', 'Meaning of Life'])
'Holy Grail'
```

## その他の数値型
### 小数型
- Python 2.4から、新たに小数という型が導入
- リテラルではなく、モジュールをインポートして関数を呼び出す、という方法で使用する
- 浮動小数点数に似ているが、小数点以下の桁数が固定される点、つまり精度が固定される点が異なっている
- 浮動小数点数に比べ、多少パフォーマンスの低下を招く恐れがある
- 合計金額の計算など、精度が一定の数値を表現するには、正確性も高まり、適切な型

```pycon:浮動小数点型の場合
>>> 0.1 + 0.1 + 0.1 - 0.3
5.5511151231257827e-017

>>> print 0.1 + 0.1 + 0.1 - 0.3
5.55111512313e-017
```

```pycon:小数型の場合
>>> from decimal import Decimal
>>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
Decimal("0.0")
```

### 集合
```pycon
>>> x = set('abcde')
>>> y = set('bdxyz')

>>> x
set(['a', 'c', 'b', 'e', 'd'])

# 集合にある要素が含まれているかを判定
>>> 'e' in x
True

# 集合の差
>>> x - y
set(['a', 'c', 'e'])

# 集合の結合
>>> x | y set(['a', 'c', 'b', 'e', 'd', 'y', 'x', 'z'])

# 集合の交差
>>> x & y set(['b', 'd'])
```

```pycon:集合の使用例
>>> engineers = set(['bob', 'sue', 'ann', 'vic'])
>>> managers = set(['tom', 'sue'])

# エンジニアでありマネージャでもある人を抜き出す
>>> engineers & managers
set(['sue'])

# いずれかのカテゴリに属する人を抜き出す
>>> engineers | managers
set(['vic', 'sue', 'tom', 'bob', 'ann'])

# マネージャでない人を抜き出す
>>> engineers - managers
set(['vic', 'bob', 'ann'])
```

### サードパーティエクステンション
- 有理数
- ベクトル
- 行列