#order #nan #float #finite #hash

no-std decorum

浮点类型的全序、等价、哈希和约束

19个版本

0.3.1 2020年5月31日
0.2.0 2020年5月4日
0.1.3 2019年1月11日
0.1.2 2018年12月1日
0.0.7 2017年11月15日

#162Rust模式

Download history 8476/week @ 2024-03-14 8558/week @ 2024-03-21 8215/week @ 2024-03-28 9207/week @ 2024-04-04 8903/week @ 2024-04-11 9437/week @ 2024-04-18 10863/week @ 2024-04-25 9738/week @ 2024-05-02 11223/week @ 2024-05-09 11987/week @ 2024-05-16 11326/week @ 2024-05-23 11519/week @ 2024-05-30 11793/week @ 2024-06-06 11204/week @ 2024-06-13 13461/week @ 2024-06-20 11537/week @ 2024-06-27

50,384 每月下载
用于 54 个crate (25直接)

MIT 许可证

90KB
2.5K SLoC

Decorum

Decorum 是一个Rust库,它为浮点表示提供全序、等价、哈希和约束。Decorum不需要std

CI Documentation Crate

全序

以下全序通过实现Ord的原始类型和代理类型(proxy types)的特质公开

[ -INF < ... < 0 < ... < +INF < NaN ]

IEEE-754浮点编码提供了多种零(-0+0)和 NaN 的表示。此排序将所有零和 NaN 表示视为相等,这与 标准部分排序 不同。

某些代理类型不允许无序的 NaN 值,因此支持基于非 NaN 浮点值有序子集的全序(见下文)。

代理类型

Decorum公开了几个代理(包装)类型。代理类型提供了两个主要功能:它们通过EqOrdHash特质实现全序和等价,并且它们约束它们可以表示的浮点值类别。不同的类型定义应用不同的约束,其中Total类型不施加任何约束。

类型 别名 特质实现 不允许的值
全序 编码+实数+无穷大+NaN+浮点数
非NaN N32, N64 编码+实数+无穷大 NaN
有限 R32, R64 编码+实数 NaN, -INF, +INF

代理类型实现了常见的操作特性,例如 AddMul。这些类型还实现了来自 num-traits 包(例如 FloatNumNumCast 等)的数值特性,以及 Decorum 提供的更具体的特性,如 RealNan

约束违规会导致 panic。例如,NotNan 有助于避免或追踪计算中 NaN 的来源,而 Total 提供了有用的功能,而不会引起任何 panic,因为它允许任何 IEEE-754 浮点值。

代理类型应作为原始类型在大多数应用程序中的直接替换,最常见的例外是初始化(因为它需要转换)。序列化可选支持 serde,并通过 serialize-serdeapprox 功能分别支持近似比较。

特性

特性对于泛型编程至关重要,但某些代理类型使用的约束阻止它们实现 Float 特性,因为它暗示了 -INF+INFNaN(以及它们对应的特性实现)的存在。

Decorum 提供了更细粒度的特性,这些特性将这些 API 区分开来:RealInfiniteNanEncoding。原始浮点类型实现了所有这些特性,代理类型实现了与其约束一致的特性。

例如,希望泛型处理表示实数和无穷大的浮点类型的代码可以使用 InfiniteReal 特性的界限

use decorum::{Infinite, Real};

fn f<T>(x: T, y: T) -> T
where
    T: Infinite + Real,
{
    let z = x / y;
    if z.is_infinite() {
        y
    }
    else {
        z
    }
}

Decorum 和 num-traits 都提供了 RealFloat 特性。这些特性有些不同,并不总是可互换的。Decorum 尽可能地实现了两个包中的特性。例如,Total 实现了来自 Decorum 和 num-traitsFloat

转换

代理类型通过转换为原始浮点类型和其他代理类型来使用。

转换 输入 输出 违规
from_inner 原始类型 代理类型 panic
into_inner 代理类型 原始类型 n/a
from_subset 代理类型 代理类型 n/a
into_superset 代理类型 代理类型 n/a

from_innerinto_inner 转换将原始浮点值移动到代理中并从代理中移出。into_supersetfrom_subset 转换提供了在不同但兼容的约束之间转换的低成本方法。所有转换还支持标准的 FromInto 特性,这些特性也可以应用于字面量

use decorum::R32;

fn f(x: R32) -> R32 {
    x * 2.0
}
let y: R32 = 3.1459.into();
let z = f(2.7182.into());
let w: f32 = z.into();

原始类型

代理类型实现了 EqHashOrd,但有时使用此类类型可能不可行或不方便。可以使用特性来与原始浮点值一起用于排序、等价性和散列。

浮点特性 通用特性
FloatEq Eq
FloatHash Hash
FloatOrd Ord

这些特性使用了与代理类型相同的全序和等价规则。它们不仅为基本类型实现,也为切片实现了。

use decorum::cmp::FloatEq;

let x = 0.0f64 / 0.0f64; // `NaN`.
let y = f64::INFINITY + f64::NEG_INFINITY; // `NaN`.
assert!(x.float_eq(&y));

let xs = [1.0f64, f64::NAN, f64::INFINITY];
let ys = [1.0f64, f64::NAN, f64::INFINITY];
assert!(xs.float_eq(&ys));

依赖项

~130–365KB