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 模式
每月 250 次下载
在 fixnum-approx-eq 中使用
185KB
3.5K SLoC
fixnum
具有显式舍入的定点数。
lib.rs
:
fixnum
定点数 具有显式舍入。
使用各种有符号整数类型来存储数字。
功能
在 Cargo.toml
中启用它们
i128
— 支持i128
布局,在乘法和除法中提升为内部实现的I256
。i64
— 支持i64
布局,在乘法和除法中提升为i128
。i32
— 支持i32
布局,在乘法和除法中提升为i64
。i16
— 支持i16
布局,在乘法和除法中提升为i32
。parity
— 支持parity-scale-codec
(Encode
和Decode
实现)。serde
— 支持serde。
schemars
— 支持schemars。
std
— 默认启用。
至少需要启用 i128
、i64
、i32
、i16
中的一个。
示例
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