[−][src]Crate fixnum
fixnum
Fixed-point numbers with explicit rounding.
Uses various signed integer types to store the number. The following are available by default:
i16
— promotes toi32
for multiplication and division,i32
— promotes toi64
(for mul, div),i64
— promotes toi128
(for mul, div).
Features
Turn them on in Cargo.toml
:
i128
—i128
layout support which will be promoted to internally implementedI256
for multiplication and division.parity
—parity-scale-codec
support (Encode
andDecode
implementations).
Example
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);
Available operations
Method | Example (pseudo-code) | Description |
---|---|---|
cadd | let result: Result<FixedPoint, ArithmeticError> = a.cadd(b) | Checked addition. Returns Err on overflow. |
csub | let result: Result<FixedPoint, ArithmeticError> = a.csub(b) | Checked subtraction. Returns Err on overflow. |
cmul | let result: Result<FixedPoint, ArithmeticError> = a.cmul(b) | Checked multiplication. Returns Err on overflow. This is multiplication without rounding, hence it's available only when at least one operand is integer. |
rmul | let result: Result<FixedPoint, ArithmeticError> = a.rmul(b, RoundMode::Ceil) | Checked rounding multiplication. Returns Err on overflow. Because of provided RoundMode it's possible across the FixedPoint values. |
rdiv | let result: Result<FixedPoint, ArithmeticError> = a.rdiv(b, RoundMode::Floor) | Checked rounding division. Returns Err on overflow. Because of provided RoundMode it's possible across the FixedPoint values. |
cneg | let result: Result<FixedPoint, ArithmeticError> = a.cneg() | Checked negation. Returns Err on overflow (you can't negate MIN value). |
integral | let y: {integer} = x.integral(RoundMode::Floor) | Takes rounded integral part of the number. |
saturating_add | let z: FixedPoint = x.saturating_add(y) | Saturating addition |
saturating_sub | let z: FixedPoint = x.saturating_sub(y) | Saturating subtraction |
saturating_mul | let z: FixedPoint = x.saturating_mul(y) | Saturating multiplication. This is multiplication without rounding, hence it's available only when at least one operand is integer. |
saturating_rmul | let z: FixedPoint = x.saturating_rmul(y, RoundMode::Floor) | Saturating rounding multiplication |
Implementing wrapper types.
It's possible to restrict the domain in order to reduce chance of mistakes.
Note that convenient fixnum!
macro works with wrapper types too.
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));
Re-exports
pub use typenum; |
Modules
ops |
Macros
fixnum | Macro to create fixed-point "literals". Contains |
fixnum_const | Macro to create fixed-point const "literals". |
impl_op |
Structs
FixedPoint | Abstraction over fixed point numbers of arbitrary (but only compile-time specified) size and precision. |
Enums
ArithmeticError | |
ConvertError | |
FromDecimalError |
Traits
Precision |