Progrust Library.

// dictionary

比較演算子.

比較演算子は、2つの値の等価性(==・!=)や大小関係(<・<=・>・>=)を調べる演算子です。結果は必ず論理値型になるため、if式の条件や論理演算子の組み合わせにそのまま渡せます。
左右の値は原則として同じ型である必要があり、型が違えば暗黙に変換されることなくコンパイルエラーになります。

演算子 意味 例
== 等しい 3 == 3 → true
!= 等しくない 3 != 5 → true
< より小さい 3 < 5 → true
<= 以下 3 <= 3 → true
> より大きい 5 > 3 → true
>= 以上 3 >= 5 → false
fn main() {
    let price = 120; // りんご1個の値段(円)
    let budget = 500; // 予算(円)

    let affordable: bool = price <= budget; // 比較の結果は論理値型
    println!("1個買えるか: {}", affordable);
    println!("3個で予算オーバーか: {}", price * 3 > budget);
    println!("予算ぴったりか: {}", price == budget);
}
Playgroundで開く

左右の型は揃える必要がある

i32とi64のような整数型は、ビット幅が違うだけでも別の型として扱われるため、そのまま比較することはできません。asによるキャストなどで型を揃えます。

fn main() {
    let count: i32 = 3;
    let total: i64 = 1000;
    println!("{}", count < total); // エラー: E0308(i32とi64は比較できない)
}
Playgroundで開く

(count as i64) < totalのように片方を変換すれば比較できます。なお、リテラルだけであれば型推論で型が揃うため、3 < 1000はそのまま書けます。

ただし、文字列型(String)と&strのように、標準ライブラリが異なる型同士の比較を用意している例外もあります(補足「実体はPartialEq・PartialOrdトレイト」を参照)。

補足

値はムーブされない

比較演算子は、算術演算子などと違ってオペランドを暗黙に借用します。a == bはstd::cmp::PartialEq::eq(&a, &b)と等価に展開されるため2、比較しただけではムーブが起きず、比較後も元の変数をそのまま使えます。

数値以外も比較できる

文字型・文字列スライス・タプル型・配列型なども比較できます。文字列やタプル・配列は辞書式比較(先頭の要素から順に比較し、決着が付いた時点で結果が決まる)で大小が決まります。

fn main() {
    println!("{}", 'あ' < 'い'); // true(Unicodeスカラー値の順)
    println!("{}", "りんご" < "りんごジュース"); // true(前方一致なら短いほうが小さい)
    println!("{}", [1, 2, 3] < [1, 3, 4]); // true(2要素目で決着)
}
Playgroundで開く

ただし文字列の比較はバイト値の順であり、いわゆるアルファベット順・五十音順とは一致しません。大文字は小文字より小さいため、"Banana" < "apple"はtrueになります。

実体はPartialEq・PartialOrdトレイト

==・!=はPartialEq、<などの大小比較はPartialOrdというトレイトのメソッド呼び出しに展開されます2。PartialEq<Rhs = Self>は右辺の型を型引数に取り、その既定値がSelfであるために「同じ型同士」が原則になっています3。標準ライブラリは一部の組み合わせに異なる型同士の実装も提供しており、文字列型と&str、ベクタ(Vec)と[T; N]は==で比較できます(ただしこの例外は等価比較だけで、<などは同じ型同士に限られます)。

自作の構造体や列挙型は、そのままでは比較演算子を適用できません(エラー: E0369)。#[derive(PartialEq)]を付けると==・!=が、#[derive(PartialOrd)]も併せて付けると大小比較が使えるようになります4。

#[derive(PartialEq, PartialOrd)]
struct Price(u32); // 税込価格(円)

fn main() {
    println!("{}", Price(120) < Price(200)); // deriveで比較できるようになる
    println!("{}", String::from("りんご") == "りんご"); // Stringと&strの例外
}
Playgroundで開く

4つのトレイトの継承関係や、Partialが付く側と付かない側の違いは比較のトレイトで扱っています。演算子をトレイトの実装として定義するという仕組み全体は演算子オーバーロードを参照してください。

NaNとの比較

浮動小数点型のNaN(非数)は自分自身とも等しくならないため、==だけでなく<・<=・>・>=もすべてfalseを返します(!=だけは逆にtrueになります)。値の大小で分岐するコードでは、どちらの枝にも入らない場合があることに注意してください。

Footnotes

  1. The Rust Reference: Expressions(演算子の優先順位表で、比較演算子の結合性は「Require parentheses」とされている) ↩

  2. The Rust Reference: Comparison operators ↩ ↩2

  3. std::cmp::PartialEq ↩

  4. std::cmp::PartialOrd(Derivable) ↩

この辞書が使われているページ

backlinks 5

  1. 辞書演算子オーバーロード
  2. 辞書比較のトレイト
  3. 辞書論理演算子
  4. 本動かして学ぶRustプログラミング問題集 › 第19章 derive属性と標準トレイト
  5. 本動かして学ぶRustプログラミング問題集 › 第2章 基本の型と演算