17 个不稳定版本 (8 个破坏性更新)

0.9.2 2023 年 3 月 2 日
0.9.1 2022 年 10 月 10 日
0.9.0 2022 年 9 月 8 日
0.8.0 2022 年 6 月 23 日
0.2.3 2020 年 12 月 30 日

#842 in Rust 模式

Download history 53/week @ 2024-03-13 24/week @ 2024-03-20 46/week @ 2024-03-27 142/week @ 2024-04-03 60/week @ 2024-04-10 270/week @ 2024-04-17 42/week @ 2024-04-24 22/week @ 2024-05-01 11/week @ 2024-05-08 30/week @ 2024-05-15 28/week @ 2024-05-22 43/week @ 2024-05-29 57/week @ 2024-06-05 27/week @ 2024-06-12 89/week @ 2024-06-19 50/week @ 2024-06-26

每月 250 次下载
fixnum-approx-eq 中使用

MIT/Apache

185KB
3.5K SLoC

fixnum

具有显式舍入的定点数。

Crates.io Documentation MIT licensed Build Status


lib.rs:

fixnum

定点数 具有显式舍入。

使用各种有符号整数类型来存储数字。

功能

Cargo.toml 中启用它们

  • i128 — 支持 i128 布局,在乘法和除法中提升为内部实现的 I256
  • i64 — 支持 i64 布局,在乘法和除法中提升为 i128
  • i32 — 支持 i32 布局,在乘法和除法中提升为 i64
  • i16 — 支持 i16 布局,在乘法和除法中提升为 i32
  • parity — 支持 parity-scale-codec (EncodeDecode 实现)。
  • serde — 支持 serde
  • schemars — 支持 schemars
  • std — 默认启用。

至少需要启用 i128i64i32i16 中的一个。

示例

use fixnum::{FixedPoint, typenum::U9, ops::{CheckedAdd, RoundingMul, RoundMode::*, Zero}};

/// Signed fixed point amount over 64 bits, 9 decimal places.
///
/// MAX = (2 ^ (BITS_COUNT - 1) - 1) / 10 ^ PRECISION =
///     = (2 ^ (64 - 1) - 1) / 1e9 =
///     = 9223372036.854775807 ~ 9.2e9
/// ERROR_MAX = 0.5 / (10 ^ PRECISION) =
///           = 0.5 / 1e9 =
///           = 5e-10
type Amount = FixedPoint<i64, U9>;

let a: Amount = "0.1".parse()?;
let b: Amount = "0.2".parse()?;
assert_eq!(a.cadd(b)?, "0.3".parse()?);

let expences: Amount = "0.000000001".parse()?;
// 1e-9 * (Floor) 1e-9 = 0
assert_eq!(expences.rmul(expences, Floor)?, Amount::ZERO);
// 1e-9 * (Ceil) 1e-9 = 1e-9
assert_eq!(expences.rmul(expences, Ceil)?, expences);

可用操作

方法 示例(伪代码) 描述
cadd letresult: Result<定点数,算术错误> =a.cadd(b) 检查加法。溢出时返回 Err
csub letresult: Result<定点数,算术错误> =a.csub(b) 检查减法。溢出时返回 Err
cmul letresult: Result<定点数,算术错误> =a.cmul(b) 检查乘法。溢出时返回 Err。这是不带舍入的乘法,因此仅当至少有一个操作数是整数时才可用。
rmul letresult: Result<定点数,算术错误> =a.rmul(b, 舍入模式::向上取整) 检查舍入乘法。溢出时返回 Err。由于提供了 RoundMode,因此可以在 FixedPoint 值之间进行。
rdiv letresult: Result<定点数,算术错误> =a.rdiv(b, 舍入模式::向下取整) 检查舍入除法。溢出时返回 Err
rsqrt letresult: Result<定点数,算术错误> =a.rsqrt(舍入模式::向下取整) 检查舍入平方根。对于负参数返回 Err
cneg letresult: Result<定点数,算术错误> =a.cneg() 检查取反。溢出时返回 Err(你不能对 MIN 取反)。
integral lety: {整数} =x.integral(舍入模式::向下取整) 取数字的舍入整数部分。
saturating_add letz:定点数=x.saturating_add(y) 饱和加法
saturating_sub letz:定点数=x.saturating_sub(y) 饱和减法
saturating_mul letz:定点数=x.saturating_mul(y) 饱和乘法。这是不带舍入的乘法,因此仅当至少有一个操作数是整数时才可用。
saturating_rmul letz:定点数=x.saturating_rmul(y, 舍入模式::向下取整) 饱和舍入乘法

实现包装类型。

可以限制域以减少错误的机会。请注意,方便的 fixnum! 也与包装类型一起使用。

use derive_more::From;
use fixnum::{impl_op, typenum::U9, FixedPoint, fixnum};

type Fp64 = FixedPoint<i64, U9>;
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, From)]
struct Size(i32);
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, From)]
struct Price(Fp64);
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, From)]
struct PriceDelta(Fp64);
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, From)]
struct Amount(Fp64);
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, From)]
struct Ratio(Fp64);

impl_op!(Size [cadd] Size = Size);
impl_op!(Size [csub] Size = Size);
impl_op!(Size [rdiv] Size = Ratio);
impl_op!(Size [cmul] Price = Amount);
impl_op!(Price [csub] Price = PriceDelta);
impl_op!(Price [cadd] PriceDelta = Price);
impl_op!(Price [rdiv] Price = Ratio);
impl_op!(Price [rmul] Ratio = Price);
impl_op!(PriceDelta [cadd] PriceDelta = PriceDelta);
impl_op!(Amount [cadd] Amount = Amount);
impl_op!(Amount [csub] Amount = Amount);

// Use it.
use fixnum::ops::*;
let size = Size(4);
let price = fixnum!(4.25, 9); // compile-time
let amount = size.cmul(price)?;
assert_eq!(amount, fixnum!(17, 9));

依赖项

~0.5–1.2MB
~29K SLoC