Rustの数値型をマスターしたい（Part1）

昨年からRustを学んでいるのですが、Rustは数値型が複雑で、今はまだなんとなく使うことしかできていません。そこで、Qiitaでのアウトプットを通じて、Rustの数値型をマスターしていきたいと思います。

## 今回の内容

- 数値型一覧
- 数値型の選び方


## 数値型一覧

まず、Rustには使える数値型がいくつかあります。

頭についているアルファベット（`u`、`i`、`f`）は数値の種類を表します。

- `u` => 符号なし整数（unsigned integer）
    - つまり、自然数と0
- `i` => 符号あり整数（signed integer）
    - つまり、整数（プラスもマイナスも）
- `f` => 浮動小数点（floating point）
    - つまり、小数
    - 浮動小数点には、表現できる正確さに限界があります。
    - その点については、今後の記事でまとめたいと思います。

その後ろの数字は、そのデータの大きさであるビット数を表しています。
それらを組み合わせると、以下のような範囲の数値を表現する型となります。


### 符号なし整数（unsigned integer）
| 型 | 最小値 | 最大値 |
|:--|:--|:--|
| u8 | 0 | 255 |
| u16 | 0 | 65535 |
| u32 | 0 | 4294967295 |
| u64 | 0 | 18446744073709551615 |
| u128 | 0 | 340282366920938463463374607431768211455 |

### 符号あり整数（signed integer）
| 型 | 最小値 | 最大値 |
|:--|:--|:--|
| i8 | -128 | 127 |
| i16 | -32768 | 32767 |
| i32 | -2147483648 | 2147483647 |
| i64 | -9223372036854775808 | 9223372036854775807 |
| i128 | -170141183460469231731687303715884105728 | 170141183460469231731687303715884105727 |

### 浮動小数点（floating point）
| 型 | 最小値 | 最大値 |
|:--|:--|:--|
| f32 | -3.4028235e38 | 3.4028235e38 |
| f64 | -1.7976931348623157e308 | 1.7976931348623157e308 |

※e38やe308というのは、10の38乗倍や10の308乗倍の事です。
（例）1.23e5 => 123000

### usize、isize
このほかにusize、isizeという型があり、それぞれマシンのビット数に依存します。
（例）64ビットマシンならusize=>u64、isize=>i64
参考：[Numeric types - The Rust Reference](https://doc.rust-lang.org/reference/types/numeric.html)
参考：[Rust - 基本的なデータ型について](https://qiita.com/Rinrin0413/items/2bc99fe2c79cb2b492bc)


## 数値型の選び方

### 数値型を選ぶ際の観点
調べてみたところ、以下のような観点が数値型を選ぶ際の基準となりそうです。

#### 動作効率に関する観点
- Rustの公式ドキュメントでは、i32がお勧めされている
    - 参考：[Data Types - The Rust Programming Language](https://doc.rust-lang.org/book/ch03-02-data-types.html)
- 処理速度では32ビットが速い場合が多い
    - 条件によって、8ビットが速い場合や64ビットが速い場合などあるようですが、32ビットが安定して速い様子
    - 参考：[[Rust] 整数型の四則演算ベンチマーク](https://qiita.com/osanshouo/items/8a6d434adf7c2ad236a8)
- 符号付き`i`でも符号なし`u`でも、処理速度は変わらない
    - 参考https://www.reddit.com/r/rust/comments/931leq/why_are_i32s_the_fastest/
- ビットが小さいと、メモリの使用量が減る
    - 巨大な配列などの場合には大きな違いになる

#### その他の観点
- Vecや配列などのインデックスとして使用する場合=>usize ~~かisize~~を利用
    - [公式ドキュメント](https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-types)では、isizeも使えると記載されているのですが、isizeは使えず、usizeだけとなっているようです。（2022/2/12追記）

    ```
the type `[u32]` cannot be indexed by `isize`
slice indices are of type `usize` or ranges of `usize`
help: the trait `std::slice::SliceIndex<[u32]>` is not implemented for `isize`
note: required because of the requirements on the impl of `std::ops::Index<isize>` for `[u32]`rustc(E0277)
    ```
※インデックスにisizeを使用した場合のエラーメッセージ（Rustのv1.56.1で確認）

- 浮動小数点型については、f32を使う場合は以下の通り、限定的
    - メモリ消費を最大限減らしたい場合
    - double-precisionがサポートされていない環境
    - single-precisionの方が処理速度が速い環境

### 数値型を選ぶ際のフローチャート

上記の観点を、フローチャートにまとめました。
まだまだ学習中の個人の意見ですので、ご意見等あれば、コメントいただけると大変嬉しいです。


#### フローチャート①
<img width="750px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102360/8988adac-eff2-c0f6-37ee-52295581e729.png">

#### フローチャート②（ビット数の決め方）
<img width="500px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102360/286168e7-e5e1-e03c-d3d7-c9e2685c9669.png">


### まとめ
冒頭でも述べた通り、Rustの数値型はまだまだ奥が深いですが、今回の記事はここまでで区切り、次回以降の記事で以下の内容をまとめていきたいと思います。

- float型の説明
- オーバーフロー・アンダーフローについて
- 型変換の仕方
- 整数リテラル・バイトリテラルについて
- 数値型が持つ共通のメソッド