#floating-point #comparison #equals #float #almost

no-std nearly

比较IEEE浮点类型

4个版本 (破坏性)

0.4.0 2024年4月8日
0.3.0 2024年2月19日
0.2.0 2023年5月15日
0.1.0 2023年3月14日

#123调试

Download history 6/week @ 2024-05-21 34/week @ 2024-05-28 282/week @ 2024-06-04 353/week @ 2024-06-11 329/week @ 2024-06-18 298/week @ 2024-06-25 374/week @ 2024-07-02 429/week @ 2024-07-09 157/week @ 2024-07-16 486/week @ 2024-07-23 246/week @ 2024-07-30 228/week @ 2024-08-06

每月1,133 次下载

MIT 许可证

120KB
2K SLoC

nearly

license  crate  doc  ci

通过nearly比较来比较IEEE浮点类型。

在比较浮点类型时,由于它们的精度有限,它们可能不完全相同。以下是一个示例,其中a和b看起来是相同的,但实际上并不相同

let a: f32 = 1.0 + 1.04 + 1.1;
let b: f32 = 3.14;

assert!(a == b); // <-- PANICS

此crate提供宏以执行具有一些容忍度的比较。

use nearly::nearly;
assert!( nearly!(a == b) ); // <-- OK

用法

使用nearly比较的最简单方法是调用nearly!宏。宏通过使用提供的容忍度返回布尔值,以确定比较是否为真或假。

比较可以是

  • a == b用于测试a是否几乎等于b
  • a != b用于测试a是否不几乎等于b
  • a < b用于测试a是否严格小于b但不几乎等于b
  • a <= b用于测试a是否严格小于b或几乎等于b
  • a > b用于测试a是否严格大于b但不几乎等于b
  • a >= b用于测试a是否严格大于b或几乎等于b

使用的容忍度可以是

  • eps用于绝对epsilon容忍度
  • ulps 表示基于 ulps 的容差
  • tol 表示绝对 epsilon 和基于 ulps 的容差
  • default 表示使用默认值进行绝对 epsilon 和基于 ulps 的容差

以下是示例调用

use nearly::{nearly, Tolerance};

let a: f32 = 1.0 + 1.04 + 1.1;
let b: f32 = 3.14;

// use absolute epsilon tolerance
nearly!(a == b, eps = 0.001);

// use ulps based tolerance
nearly!(a == b, ulps = 5);

// use absolute epsilon and ulps based tolerance
nearly!(a == b, eps = 0.001, ulps = 5);
nearly!(a == b, tol = Tolerance::new(0.001, 5));

// use default absolute epsilon and default ulps based tolerance
nearly!(a == b);

还有两个可以使用的宏:assert_nearly!debug_assert_nearly!。如果近似的比较结果为假,它们会引发 panic。它们的签名与 nearly! 宏相同。

use nearly::{assert_nearly, debug_assert_nearly, Tolerance};

assert_nearly!(a == b, eps = 0.001);
assert_nearly!(a == b, ulps = 5);
assert_nearly!(a == b, eps = 0.001, ulps = 5);
assert_nearly!(a == b, tol = Tolerance::new(0.001, 5));
assert_nearly!(a == b);

debug_assert_nearly!(a == b, eps = 0.001);
debug_assert_nearly!(a == b, ulps = 5);
debug_assert_nearly!(a == b, eps = 0.001, ulps = 5);
debug_assert_nearly!(a == b, tol = Tolerance::new(0.001, 5));
debug_assert_nearly!(a == b);

近似的特性也适用于许多其他持有浮点数的类型,如容器、映射、指针或元组。以下是比较两个浮点数数组的一个示例。

use nearly::nearly;

let a: [f32; 4] = [1.1, 2.2, 2.2, 4.4];
let b: [f32; 4] = [1.1, 2.2, 3.3, 4.4];

nearly!(a <= b, eps = 0.001, ulps = 5);

推导近似的特性

向自己的类型添加近似比较的最简单方法是推导近似的特性。只需推导 NearlyEqNearlyOrd,即可为您的类型提供全面支持。

use nearly::{assert_nearly, NearlyEq, NearlyOrd};

#[derive(Debug, NearlyEq, NearlyOrd)]
struct Point {
    x: f32,
    y: f32,
}

let a = Point { x: 1.23, y: 4.56 };
let b = Point { x: 1.23, y: 4.567 };

assert_nearly!(a == b, eps = 0.01);
assert_nearly!(a <= b, eps = 0.01);

要使用 assert_nearly!debug_assert_nearly! 宏,您的类型还必须实现 Debug 特性。

您可以推导以下特性

  • NearlyEqEps:启用具有绝对 epsilon 容差的近似支持
  • NearlyEqUlps:启用基于 ulps 容差的近似支持
  • NearlyEqTol:启用具有绝对 epsilon 和 ulps 容差的近似支持
  • NearlyEq:启用具有绝对 epsilon 和 ulps 容差的近似支持,并使用默认值
  • NearlyOrdEps:启用具有绝对 epsilon 容差的近似排序支持
  • NearlyOrdUlps:启用基于 ulps 容差的近似排序支持
  • NearlyOrdTol:启用具有绝对 epsilon 和 ulps 容差的近似排序支持
  • NearlyOrd:启用具有绝对 epsilon 和 ulps 容差的近似排序支持,并使用默认值

依赖项

~295–740KB
~17K SLoC