LoginSignup
4
2

More than 3 years have passed since last update.

Rust勉強中 - その6 -> 浮動小数点数

Last updated at Posted at 2019-09-28

自己紹介

出田 守と申します。
しがないPythonプログラマです。
情報セキュリティに興味があり現在勉強中です。CTFやバグバウンティなどで腕を磨いています。主に低レイヤの技術が好きで、そっちばかり目が行きがちです。

Rustを勉強していくうえで、読んで学び、手を動かし、記録し、楽しく学んでいけたらと思います。

環境

新しい言語を学ぶということで、普段使わないWindowsとVimという新しい開発環境で行っています。
OS: Windows10 Home 64bit 1903
CPU: Intel Core i5-3470 @ 3.20GHz
Rust: 1.38.0
RAM: 8.00GB
Editor: Vim 8.1.1
Terminal: PowerShell

前回

前回は整数型について学びました。
Rust勉強中 - その5

今回はRustの浮動小数点数を学びます。

浮動小数点数

Rustの浮動小数点数はIEEE 754-2008の単精度、倍精度の浮動小数点数、正と負の無限大、正と負の0、NaNなどをサポートしています。

単精度浮動小数点数

範囲
f32 -3.4028235e38 ~ 3.4028235e38

倍精度浮動小数点数

範囲
f64 -1.7976931348623157e308 ~ 1.7976931348623157e308

浮動小数点数リテラル

Rustでは整数リテラルと浮動小数点数リテラルは区別されます。なので、浮動小数リテラルを表現するには明示的に型を宣言するか、小数部または指数部を指定します。
型推論の際にf32型とf64型どちらも表現できる場合はf64型が選択されます。
整数リテラルと同じように、アンダーバーを含めることもできます。ただし、小数点直後のアンダーバーはエラーが出ました。

浮動小数リテラル 補足
1f32 f32型を宣言
1_f32 整数部にアンダーバー
1f64 f64型を宣言
1.0f32 f32型を宣言
1_.0f32 f32型で整数部にアンダーバー
1.1 f64型で型推論
1_.1 f64型で整数部にアンダーバー
1.1_1 f64型で小数部にアンダーバー
1. 小数点を付けてf64型で型推論
1e2 指数部を付けてf64で型推論(=100)
1_e2 指数部前にアンダーバー
1e-2 指数部を付けてf64で型推論(=0.01)
1_e-2 指数部前にアンダーバー

浮動小数点数のキャスト

浮動小数点数にもas演算子で型変換ができます。また、整数型と浮動小数点数との型変換もできます。

変換 結果 補足
1.1f64 as f32 1.1f32 f64型からf32型へ変換
1.1f32 as f64 1.100000023841858f64 f32型からf64型へ変換
std::f64::MAX as f32 inff32 f64型最大値からf32型へ変換
std::f32::MAX as f64 3.4028234663852886e38f64 f32型最大値からf64型へ変換
1i32 as f32 1f32 i32型からf32型へ変換
-1i32 as f32 -1f32 負のi32型からf32型へ変換
1f32 as i32 1i32 f32型からi32型へ変換
-1f32 as i32 -1i32 負のf32型からi32型へ変換
std::i32::MAX as f32 2147483600f32 i32型最大値からf32型へ変換
std::i32::MIN as f32 -2147483600f32 i32型最小値からf32型へ変換
std::i64::MAX as f32 9223372000000000000f32 i64型最大値からf32型へ変換
std::i64::MIN as f32 -9223372000000000000f32 i64型最小値からf32型へ変換
std::i32::MAX as f64 2147483647f64 i32型最大値からf64型へ変換
std::i32::MIN as f64 -2147483648f64 i32型最小値からf64型へ変換
std::i64::MAX as f64 9223372036854776000f64 i64型最大値からf64型へ変換
std::i64::MIN as f64 -9223372036854776000f64 i64型最小値からf64型へ変換
std::f32::MAX as i32 2147483647i32 f32型最大値からi32型へ変換
std::f32::MIN as i32 -2147483648i32 f32型最小値からi32型へ変換
std::f64::MAX as i32 2147483647i32 f64型最大値からi32型へ変換
std::f64::MIN as i32 -2147483648i32 f64型最小値からi32型へ変換
std::f32::MAX as i64 9223372036854775807i64 f32型最大値からi64型へ変換
std::f32::MIN as i64 -9223372036854775808i64 f32型最小値からi64型へ変換
std::f64::MAX as i64 9223372036854775807i64 f64型最大値からi64型へ変換
std::f64::MIN as i64 -9223372036854775808i64 f64型最小値からi64型へ変換

浮動小数点数のメソッド

整数型と同じく浮動小数点数にもメソッドがあります。一部を試してみます。

結果
(-0.5f64).abs() 0.5
-0.5f64.abs() -0.5
0.5f64.round() 1
0.4f64.round() 0
0.5f64.trunc() 0
std::f64::NAN.is_nan() true

浮動小数点数のメソッドもマイナスよりも優先して評価されるので注意が必要です。

浮動小数点数の調査用のプログラムは前回のソースに追記しました。

main.rs
...

fn print_float_range() {
    println!("\n[print floating point range]");
    println!("f32:     {:e} ~ {:e}", std::f32::MIN, std::f32::MAX);
    println!("f64:     {:e} ~ {:e}", std::f64::MIN, std::f64::MAX);
    println!("f64_Inf: {}",          std::f64::INFINITY);
    println!("f64_Inf: {}",          std::f64::NEG_INFINITY);
    println!("f64_nan: {}",          std::f64::NAN);
}

fn print_float_literals() {
    println!("\n[print floating point literals]");
    println!("1f32:    \ttype={}, \tdigits={}", get_type(1f32),    1f32);
    println!("1_f32:   \ttype={}, \tdigits={}", get_type(1_f32),   1_f32);
    println!("1f64:    \ttype={}, \tdigits={}", get_type(1f64),    1f64);
    println!("1.0f32:  \ttype={}, \tdigits={}", get_type(1.0f32),  1.0f32);
    println!("1_.0f32: \ttype={}, \tdigits={}", get_type(1_.0f32), 1_.0f32);
    println!("1.1:     \ttype={}, \tdigits={}", get_type(1.1),     1.1);
    println!("1_.1:    \ttype={}, \tdigits={}", get_type(1_.1),    1_.1);
    println!("1.1_1:   \ttype={}, \tdigits={}", get_type(1.1_1),   1.1_1);
    println!("1.:      \ttype={}, \tdigits={}", get_type(1.),      1.);
    println!("1e2:     \ttype={}, \tdigits={}", get_type(1e2),     1e2);
    println!("1_e2:    \ttype={}, \tdigits={}", get_type(1_e2),    1_e2);
    println!("1e-2:    \ttype={}, \tdigits={}", get_type(1e-2),    1e-2);
    println!("1_e-2:   \ttype={}, \tdigits={}", get_type(1_e-2),   1_e-2);
}

fn print_float_cast() {
    println!("\n[print floating point cast]");
    println!("1.1f64        as f32 => {}{}",   1.1f64 as f32,        get_type(1.1f64 as f32));
    println!("1.1f32        as f64 => {}{}",   1.1f32 as f64,        get_type(1.1f32 as f64));
    println!("std::f64::MAX as f32 => {:e}{}", std::f64::MAX as f32, get_type(std::f64::MAX as f32));
    println!("std::f32::MAX as f64 => {:e}{}", std::f32::MAX as f64, get_type(std::f32::MAX as f64));
    println!("1i32          as f32 => {}{}",   1i32 as f32,          get_type(1i32 as f32));
    println!("-1i32         as f32 => {}{}",   -1i32 as f32,         get_type(-1i32 as f32));
    println!("1f32          as i32 => {}{}",   1f32 as i32,          get_type(1f32 as i32));
    println!("-1f32         as i32 => {}{}",   -1f32 as i32,         get_type(-1f32 as i32));
    println!("std::i32::MAX as f32 => {}{}",   std::i32::MAX as f32, get_type(std::i32::MAX as f32));
    println!("std::i32::MIN as f32 => {}{}",   std::i32::MIN as f32, get_type(std::i32::MIN as f32));
    println!("std::i64::MAX as f32 => {}{}",   std::i64::MAX as f32, get_type(std::i64::MAX as f32));
    println!("std::i64::MIN as f32 => {}{}",   std::i64::MIN as f32, get_type(std::i64::MIN as f32));
    println!("std::i32::MAX as f64 => {}{}",   std::i32::MAX as f64, get_type(std::i32::MAX as f64));
    println!("std::i32::MIN as f64 => {}{}",   std::i32::MIN as f64, get_type(std::i32::MIN as f64));
    println!("std::i64::MAX as f64 => {}{}",   std::i64::MAX as f64, get_type(std::i64::MAX as f64));
    println!("std::i64::MIN as f64 => {}{}",   std::i64::MIN as f64, get_type(std::i64::MIN as f64));
    println!("std::f32::MAX as i32 => {}{}",   std::f32::MAX as i32, get_type(std::f32::MAX as i32));
    println!("std::f32::MIN as i32 => {}{}",   std::f32::MIN as i32, get_type(std::f32::MIN as i32));
    println!("std::f64::MAX as i32 => {}{}",   std::f64::MAX as i32, get_type(std::f64::MAX as i32));
    println!("std::f64::MIN as i32 => {}{}",   std::f64::MIN as i32, get_type(std::f64::MIN as i32));
    println!("std::f32::MAX as i64 => {}{}",   std::f32::MAX as i64, get_type(std::f32::MAX as i64));
    println!("std::f32::MIN as i64 => {}{}",   std::f32::MIN as i64, get_type(std::f32::MIN as i64));
    println!("std::f64::MAX as i64 => {}{}",   std::f64::MAX as i64, get_type(std::f64::MAX as i64));
    println!("std::f64::MIN as i64 => {}{}",   std::f64::MIN as i64, get_type(std::f64::MIN as i64));
}

fn print_float_methods() {
    println!("\n[print floating point methods]");
    println!("(-0.5f64).abs()        = {}", (-0.5f64).abs());
    println!("-0.5f64.abs()          = {}", -0.5f64.abs());
    println!("0.5f64.round()         = {}", 0.5f64.round());
    println!("0.4f64.round()         = {}", 0.4f64.round());
    println!("0.5f64.trunc()         = {}", 0.5f64.trunc());
    println!("std::f64::NAN.is_nan() = {}", std::f32::NAN.is_nan());
}

fn main() {
    // println!(">> Integer type <<");
    // print_int_range();
    // print_int_literals();
    // print_byte_literals();
    // print_int_cast();
    // print_int_methods();
    println!(">> Floating point type <<");
    print_float_range();
    print_float_literals();
    print_float_cast();
    print_float_methods();
}
$ cargo run                                                                                 Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target\debug\types.exe`
>> Floating point type <<

[print floating point range]
f32:     -3.4028235e38 ~ 3.4028235e38
f64:     -1.7976931348623157e308 ~ 1.7976931348623157e308
f64_Inf: inf
f64_Inf: -inf
f64_nan: NaN

[print floating point literals]
1f32:           type=f32,       digits=1
1_f32:          type=f32,       digits=1
1f64:           type=f64,       digits=1
1.0f32:         type=f32,       digits=1
1_.0f32:        type=f32,       digits=1
1.1:            type=f64,       digits=1.1
1_.1:           type=f64,       digits=1.1
1.1_1:          type=f64,       digits=1.11
1.:             type=f64,       digits=1
1e2:            type=f64,       digits=100
1_e2:           type=f64,       digits=100
1e-2:           type=f64,       digits=0.01
1_e-2:          type=f64,       digits=0.01

[print floating point cast]
1.1f64        as f32 => 1.1f32
1.1f32        as f64 => 1.100000023841858f64
std::f64::MAX as f32 => inff32
std::f32::MAX as f64 => 3.4028234663852886e38f64
1i32          as f32 => 1f32
-1i32         as f32 => -1f32
1f32          as i32 => 1i32
-1f32         as i32 => -1i32
std::i32::MAX as f32 => 2147483600f32
std::i32::MIN as f32 => -2147483600f32
std::i64::MAX as f32 => 9223372000000000000f32
std::i64::MIN as f32 => -9223372000000000000f32
std::i32::MAX as f64 => 2147483647f64
std::i32::MIN as f64 => -2147483648f64
std::i64::MAX as f64 => 9223372036854776000f64
std::i64::MIN as f64 => -9223372036854776000f64
std::f32::MAX as i32 => 2147483647i32
std::f32::MIN as i32 => -2147483648i32
std::f64::MAX as i32 => 2147483647i32
std::f64::MIN as i32 => -2147483648i32
std::f32::MAX as i64 => 9223372036854775807i64
std::f32::MIN as i64 => -9223372036854775808i64
std::f64::MAX as i64 => 9223372036854775807i64
std::f64::MIN as i64 => -9223372036854775808i64

[print floating point methods]
(-0.5f64).abs()        = 0.5
-0.5f64.abs()          = -0.5
0.5f64.round()         = 1
0.4f64.round()         = 0
0.5f64.trunc()         = 0
std::f64::NAN.is_nan() = true

今回はここまで。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2