PartialOrd trait
半順序
f64
はPartialOrdトレイトのみを実装している
NaNは他の値と大小が定まらない
PartialOrd
トレイトは、Rustで値の順序を比較するための標準的なトレイトです。このトレイトを実装することで、型のインスタンス間で大小比較を行うことができます。 PartialOrd
を実装している型では、 <
、 >
、 <=
、 >=
といった比較演算子を使用可能になります。
以下に詳細を解説します。
---
PartialOrd
トレイトの定義
PartialOrd
は次のように定義されています。
rustpub trait PartialOrd<Rhs = Self>: PartialEq<Rhs> {
fn partial_cmp(&self, other: &Rhs) -> Option<std::cmp::Ordering>;
fn lt(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(std::cmp::Ordering::Less))
}
fn le(&self, other: &Rhs) -> bool {
matches!(
self.partial_cmp(other),
Some(std::cmp::Ordering::Less | std::cmp::Ordering::Equal)
)
}
fn gt(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(std::cmp::Ordering::Greater))
}
fn ge(&self, other: &Rhs) -> bool {
matches!(
self.partial_cmp(other),
Some(std::cmp::Ordering::Greater | std::cmp::Ordering::Equal)
)
}
}
主なポイント
PartialOrd
を実装する型は PartialEq
も実装する必要があります。
順序比較には等価性が前提となるためです。
2. partial_cmp
メソッド
2つの値の順序を比較し、結果を Option<Ordering>
として返します。
Ordering
は以下の3つの値を持つ列挙型です:
Ordering::Less
( <
)
Ordering::Equal
( ==
)
Ordering::Greater
( >
)
比較できない場合は None
を返します(例:浮動小数点数の NaN
)。
3. デフォルト実装
lt
(<)、 le
(<=)、 gt
(>)、 ge
(>=)はデフォルトで partial_cmp
を使って実装されています。
---
カスタム型への実装
手動で実装する例
次の例は、2次元のポイントを x
座標の値で比較する場合です。
rustuse std::cmp::Ordering;
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
impl PartialEq for Point {
fn eq(&self, other: &Self) -> bool {
self.x == other.x
}
}
impl PartialOrd for Point {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.x.partial_cmp(&other.x)
}
}
fn main() {
let p1 = Point { x: 1, y: 5 };
let p2 = Point { x: 2, y: 3 };
let p3 = Point { x: 1, y: 10 };
println!("{}", p1 < p2); // true
println!("{}", p1 > p2); // false
println!("{}", p1 == p3); // true
}
#[derive(PartialOrd)]
を使う
#[derive(PartialOrd)]
を使えば、型のフィールドを順序比較可能にする自動実装が行えます。ただし、すべてのフィールドが PartialOrd
を実装している必要があります。
rust#[derive(PartialEq, PartialOrd, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let p1 = Point { x: 1, y: 5 };
let p2 = Point { x: 2, y: 3 };
println!("{}", p1 < p2); // true
println!("{}", p1 > p2); // false
}
---
PartialOrd
の特性
部分順序(Partial Order)
PartialOrd
は部分順序を表します。つまり、すべての値が比較可能であるとは限りません。この点が Ord
(全順序)との違いです。
部分順序の例
浮動小数点型( f32
, f64
)では NaN
が存在します。
NaN
は NaN < 1.0
でも NaN > 1.0
でもなく、 NaN == NaN
ですら false
です。
比較の結果が None
になるケース
次のように、 partial_cmp
が None
を返す場合があります。
rustfn main() {
let a = std::f64::NAN;
let b = 1.0;
println!("{:?}", a.partial_cmp(&b)); // None
println!("{}", a < b); // false
println!("{}", a > b); // false
}
---
Ord
は PartialOrd
を拡張したトレイトで、すべての値が順序関係を持つ場合に使用されます。
Ord
の cmp
メソッドは Ordering
を返しますが、 Option
ではないため、すべての値が比較可能であることを保証します。
たとえば、整数型や文字列型は Ord
を実装していますが、浮動小数点型( f32
, f64
)は Ord
を実装していません。
---
PartialOrd
を使うべき場面
一部の値が比較できない場合(部分順序のケース)。
特殊な比較ロジックをカスタム型に実装したい場合。
Ord
ではなく、柔軟な比較が必要な場面(例:浮動小数点や非標準的な比較)。