【Rust】整数型、浮動小数点型

1. 概要 

今回はRustの整数型、浮動小数点型について学んでいきたいと思います。

2. 整数型

他の言語と同様に、Rustも整数型を持っています。

大きな違いは、型のサイズが細かく分類されている点です。

整数型には大きく分けて「符号あり整数」と「符号なし整数」の2種類あります。

  • 符号あり整数:整数(0以上の値)と負数(0未満の値)を扱うことのできる整数型
  • 符号なし整数:整数(0以上の値)のみを扱うことのできる整数

符号あり整数では、使用ビット数により、i8、i16、i32、i64、i128、isizeが利用できます。

説明
i88ビット符号あり整数(-127~127)
i1616ビット符号あり整数(−32768~32767)
i3232ビット符号あり整数(-2147483648~2147483648)
i6464ビット符号あり整数(-9223372036854775808~9223372036854775808)
i128128ビット符号あり整数(−2の127乗~2の127乗 −1)
isizePCのCPUアーキテクチャに合ったビット分のサイズ(64ビット環境ならi64と同じ)
符号あり整数型の一覧

符号なし整数では、使用ビット数により、u8、u16、u32、u64、u128、usizeが利用できます。

説明
u88ビット符号なし整数(0~255)
u1616ビット符号なし整数(0~65535)
u3232ビット符号なし整数(0~4294967295)
u6464ビット符号なし整数(0~18446744073709551615)
u128128ビット符号なし整数(0~2の128乗 -1)
usizePCのCPUアーキテクチャに合ったビット分のサイズ(64ビット環境ならu64と同じ)
符号なし整数型の一覧

では、次にそれぞれの型の表現できる数値の最小値と最大値を知る方法をプログラムで確認してみます。

fn main() {
    println!("--- 符号あり整数 ---");
    println!("i8   = {} ~ {}", i8::MIN, i8::MAX);
    println!("i16  = {} ~ {}", i16::MIN, i16::MAX);
    println!("i32  = {} ~ {}", i32::MIN, i32::MAX);
    println!("i64  = {} ~ {}", i64::MIN, i64::MAX);
    println!("i128 = {} ~ {}", i128::MIN, i128::MAX);

    println!("--- 符号なし整数 ---");
    println!("u8   = {} ~ {}", u8::MIN, u8::MAX);
    println!("u16  = {} ~ {}", u16::MIN, u16::MAX);
    println!("u32  = {} ~ {}", u32::MIN, u32::MAX);
    println!("u64  = {} ~ {}", u64::MIN, u64::MAX);
    println!("u128 = {} ~ {}", u128::MIN, u128::MAX);

    println!("--- 利用環境によって変わる整数 ---");
    println!("isize = {} ~ {}", isize::MIN, isize::MAX);
    println!("usize = {} ~ {}", usize::MIN, usize::MAX);
    println!("isize = {}", isize::BITS);
    println!("usize = {}", usize::BITS);
}

実行します。

cargo run

結果

   Compiling hello_rust v0.1.0 (<作業ディレクトリ>/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.30s
     Running `target/debug/hello_rust`
--- 符号あり整数 ---
i8   = -128 ~ 127
i16  = -32768 ~ 32767
i32  = -2147483648 ~ 2147483647
i64  = -9223372036854775808 ~ 9223372036854775807
i128 = -170141183460469231731687303715884105728 ~ 170141183460469231731687303715884105727

--- 符号なし整数 ---
u8   = 0 ~ 255
u16  = 0 ~ 65535
u32  = 0 ~ 4294967295
u64  = 0 ~ 18446744073709551615
u128 = 0 ~ 340282366920938463463374607431768211455

--- 利用環境によって変わる整数 ---
isize = -9223372036854775808 ~ 9223372036854775807
usize = 0 ~ 18446744073709551615
isize = 64
usize = 64

先ほどの表の通りにそれぞれの型の表現できる範囲が出力されました。

私の利用しているPCは64ビットなのでisizeとusizeの表現範囲を出力しているところではそれぞれ、i64とu64の範囲が出力されています。

isize::BITS/usize::BITSは利用しているPCのビットが出力されます。

これを知っていれば、どの型でどの範囲まで利用できるか知ることができるのでわざわざググる必要もないので便利ですね。

次は簡単な演算をプログラムで確認してみましょう。

Rustも他の言語と同様に整数型に標準的な数学演算が用意されています。

足し算、引き算、掛け算、割り算、余りです。

fn main() {
    // 足し算
    let addition = 5 + 10;
    println!("5 + 10 = {}", addition);

    // 引き算
    let subtraction = 95 - 5;
    println!("95 - 5 = {}", subtraction);

    // 掛け算
    let multiplication = 4 * 30;
    println!("4 * 30 = {}", multiplication);

    // 割り算
    let division = 72 / 16;
    println!("72 / 16 = {}", division);

    // 余り
    let remainder = 43 % 5;
    println!("43 % 5 = {}", remainder);
}

実行します。

cargo run

結果

   Compiling hello_rust v0.1.0 (<作業ディレクトリ>/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.64s
     Running `target/debug/hello_rust`
5 + 10 = 15
95 - 5 = 90
4 * 30 = 120
72 / 16 = 4
43 % 5 = 3

それぞれの計算結果が出力されました。

Rustの整数型はデフォルトでi32です。それぞれの数値がi32の表現範囲内なので問題なく計算ができました。

では、異なる型で計算するとどうなるか確認してみましょう。

fn main() {
    let num_1: i8 = 127;
    let num_2: i16 = 32767;

    println!("{}", num_1 + num_2);
}

実行します。

cargo run

結果

   Compiling hello_rust v0.1.0 (<作業ディレクトリ>/hello_rust)
error[E0308]: mismatched types
 --> src/main.rs:5:28
  |
5 |     println!("{}", num_1 + num_2);
  |                            ^^^^^ expected `i8`, found `i16`

error[E0277]: cannot add `i16` to `i8`
 --> src/main.rs:5:26
  |
5 |     println!("{}", num_1 + num_2);
  |                          ^ no implementation for `i8 + i16`
  |
  = help: the trait `Add<i16>` is not implemented for `i8`

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `hello_rust` due to 2 previous errors

i8で定義した変数とi16で定義した変数の足し算をすると、エラーになりました。

Rustは型に厳しい言語で、暗黙的に型変換をすることはありません。型を変換する場合は明示的に行う必要があります。

これによって予期しない型の変換が行われることを防ぐことができます。

明示的に型を変換するプログラムを実際に書いてみます。

fn main() {
    // i8の変数を定義
    let num_1: i8 = 10;

    // i16の変数を定義
    let num_2: i16;

    // i8の変数nun_1をi16へキャスト
    num_2 = num_1 as i16;

    println!("{}", num_2);
}

実行します。

cargo run

結果

   Compiling hello_rust v0.1.0 (<作業ディレクトリ>/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.19s
     Running `target/debug/hello_rust`
10

問題なく実行できました。

i8の変数num_1とi16の変数num_2を定義し、変数num_2にi16にキャストした変数num_1を変数num_2に代入しています。

Rustで型を数値を変換する場合、「as」を使用します。

ただ、気をつけないといけないのは、i32からi8と大きい型から小さい型に変換すると8ビットを超えた分は切り捨てられます。

二進数で表すと

  • i32 : 0001 0010 1100 → 300
  • i8 : 0010 1100 → 44

となって8ビットを超えた分は消えて結果が44になるので、注意が必要です。

3. 浮動小数点型

浮動小数点型も他の言語と同様に持っています。

整数型にもあったように、Rustの浮動小数点型にもf32(32ビット)とf64(64ビット)があります。

デフォルトはf64です。

浮動小数点数は、IEEE-754規格に従って表現されています。

f32が単精度浮動小数点数、 f64が倍精度浮動小数点数です。

説明
f3232ビット単精度浮動小数点数(-3.4028235e38 ~ 3.4028235e38)
f64f64ビット倍精度浮動小数点数(-1.7976931348623157e308 ~ 1.7976931348623157e308)

では、浮動小数点型の動きを、実際にプログラムで確認してみましょう。

fn main() {
    // f64の変数を定義
    let f_num = 100.57;

    // f32の変数を定義
    let f_num_32: f32 = 30.8;

    println!("{}", f_num);
    println!("{}", f_num_32);
}

実行します。

cargo run

結果

   Compiling hello_rust v0.1.0 (<作業ディレクトリ>/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.20s
     Running `target/debug/hello_rust`
100.57
30.8

問題なく実行できました。

では、次にそれぞれの型の表現できる数値の最小値と最大値を知る方法をプログラムで確認してみます。

fn main() {
    // f32の表現範囲
    println!("--- f32の表現範囲 ---");
    println!("f32 = {:e} ~ {:e}", f32::MIN, f32::MAX);

    // f64の表現範囲
    println!("--- f64の表現範囲 ---");
    println!("f64 = {:e} ~ {:e}", f64::MIN, f64::MAX);
}

実行します。

cargo run

結果

   Compiling hello_rust v0.1.0 (/Users/ryoutaookawa/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.20s
     Running `target/debug/hello_rust`
--- f32の表現範囲 ---
f32 = -3.4028235e38 ~ 3.4028235e38

--- f64の表現範囲 ---
f64 = -1.7976931348623157e308 ~ 1.7976931348623157e308

先ほどの表の通りにそれぞれの型の表現できる範囲が出力されました。

整数型の時にも言ったのですが、Ristは型に厳しい言語です。浮動小数点型を明示的に指定している場合は小数点以下がないとエラーになります。

次のプログラムで確認してみます。

fn main() {
    // f64の変数を定義
    let f_num: f64 = 100; // 整数型を代入
    println!("{}", f_num);
}

実行します。

cargo run

結果

   Compiling hello_rust v0.1.0 (<作業ディレクトリ>/hello_rust)
error[E0308]: mismatched types
 --> src/main.rs:3:22
  |
3 |     let f_num: f64 = 100; // 整数型を代入
  |                ---   ^^^
  |                |     |
  |                |     expected `f64`, found integer
  |                |     help: use a float literal: `100.0`
  |                expected due to this

For more information about this error, try `rustc --explain E0308`.
error: could not compile `hello_rust` due to previous error

浮動小数点型の変数に整数を代入したので、エラーになりました。

また、f32の変数をf64の変数に代入しようとすると、整数型と同様にエラーななります。

fn main() {
    // f32の変数を定義
    let f_num_32: f32 = 10.5;

    // f64の変数を定義
    let f_num_64: f64;

    // f32の変数をf64の変数に代入
    f_num_64 = f_num_32;

    println!("{}", f_num_64);
}

実行します。

cargo run

結果

   Compiling hello_rust v0.1.0 (<作業ディレクトリ>/hello_rust)
error[E0308]: mismatched types
 --> src/main.rs:9:16
  |
6 |     let f_num_64: f64;
  |                   --- expected due to this type
...
9 |     f_num_64 = f_num_32;
  |                ^^^^^^^^ expected `f64`, found `f32`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `hello_rust` due to previous error

整数型と同様に浮動小数点型にも数学演算が用意されています。

fn main() {
    // 足し算
    let addition = 5.8 + 10.7;
    println!("5.8 + 10.7 = {}", addition);

    // 引き算
    let subtraction = 39.5 - 28.9;
    println!("39.5 - 28.9 = {}", subtraction);

    // 掛け算
    let multiplication = 4.5 * 30.7;
    println!("4.5 * 30.0 = {}", multiplication);

    // 割り算
    let division = 72.0 / 16.0;
    println!("72.0 / 16.0 = {}", division);

    // 余り
    let remainder = 43.7 % 20.9;
    println!("43.7 % 20.9 = {}", remainder);
}

実行します。

cargo run

結果

   Compiling hello_rust v0.1.0 (<作業ディレクトリ>/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.37s
     Running `target/debug/hello_rust`
5.8 + 10.7 = 16.5
39.5 - 28.9 = 10.600000000000001
4.5 * 30.0 = 138.15
72.0 / 16.0 = 4.5
43.7 % 20.9 = 1.9000000000000057

問題なくそれぞれの結果が出力されました。

4. まとめ

今回は、Rustの整数型、浮動小数点型についてやっていきました。

型に厳しいので予期せず型の変換が起きることがないので安心ですね。

仮に、どこかで型の変換が行われていてエラーが発生していたとしても容易に原因の特定ができるので楽です。

5. 参考

https://qiita.com/deta-mamoru/items/5f8399757c9c79997abf

https://qiita.com/deta-mamoru/items/9c2596a617fdf707ec4f

投稿者プロフィール

OkawaRyouta
最新の投稿

関連記事

  1. 【Rust】文字型、論理値型

  2. 【Rust】列挙型

  3. 【Rust】借用と参照、ライフタイム

  4. 【Rust】構造体

  5. 【Rust】ベクタ、スライス

  6. 【Rust】タプル型、配列型

最近の記事

  1. raspberrypi

制作実績一覧

  1. Checkeys