#decimal #float #numeric #fraction

fraction

Lossless fractions and decimals; drop-in float replacement

18 unstable releases (5 breaking)

0.6.2 May 19, 2019
0.6.1 Mar 28, 2019
0.6.0 Feb 4, 2019
0.5.0 Nov 25, 2018
0.1.0 Jan 24, 2016

#57 in Data structures

Download history 74/week @ 2019-12-01 89/week @ 2019-12-08 20/week @ 2019-12-15 29/week @ 2019-12-22 4/week @ 2019-12-29 17/week @ 2020-01-05 189/week @ 2020-01-12 78/week @ 2020-01-19 88/week @ 2020-01-26 10/week @ 2020-02-02 25/week @ 2020-02-09 37/week @ 2020-02-16 76/week @ 2020-02-23 12/week @ 2020-03-01 161/week @ 2020-03-08 22/week @ 2020-03-15

243 downloads per month
Used in 7 crates (5 directly)

MIT/Apache

405KB
10K SLoC

Fraction

Lossless fractions and decimals; drop-in float replacement

CircleCI Documentation Current Version on crates.io MIT / Apache2 License

Features

  • Drop in replacement for floats with the exception for NaN == NaN so that it's hashable
  • It's hashable, so may be used as values in Sets and keys in dictionaries and hash maps
  • Fraction type, representing floats as fractions
  • Decimal type, based on Fraction type, represents floats as decimals
  • DynaInt implements dynamically growing integer type that performs checked math and avoids stack overflows
  • PostgreSQL integration for Numeric/Decimal type (with no extra memory allocations)
  • Juniper integration for both fractions and decimals
  • Generic integer conversions, such as i8 -> u8, usize -> u8 and so on
  • Lossless division with no allocations and infinite precision

Documentation

Here: Documentation

Examples

Formatting

use fraction::Fraction;

let fraction = Fraction::new(7, 4);

assert_eq!("7/4", format!("{}", fraction));
assert_eq!("1.75", format!("{:.2}", fraction));
assert_eq!("1.750", format!("{:#.3}", fraction));

Simple arithmetic

use fraction::Fraction;

fn main () {
  let mut fr = Fraction::zero ();

  fr = fr + Fraction::from (2);   // 0 + 2   = 2
  fr = fr / Fraction::from (0.5); // 2 / 0.5 = 4

  assert_eq! (fr, Fraction::from (4));
  assert_eq! (4.0f64, fr.to_f64 ());
}

Decimal

type D = fraction::Decimal;

let result = D::from(0.5) / D::from(0.3);
assert_eq!(format!("{:.4}", result), "1.6666");

Using as keys for a HashMap

use std::collections::HashMap;
use fraction::Fraction;

fn main () {
  let f = Fraction::from (0.75);

  let mut map: HashMap<Fraction, ()> = HashMap::new ();

  map.insert (f, ());

  assert! (map.contains_key (&Fraction::new (3u64, 4u64)));   // 0.75 == 3/4
  assert! (map.contains_key (&Fraction::new (6u64, 8u64)));   // 0.75 == 6/8
  assert! (map.contains_key (&Fraction::new (12u64, 16u64))); // 0.75 == 12/16
  assert! (! map.contains_key (&Fraction::from (0.5))); // 0.75 != 1/2
}

Generic integer conversion

use fraction::{Sign, GenericFraction};

type F = GenericFraction<u32>;

let fra = F::new_generic(Sign::Plus, 1i8, 42usize).unwrap();
assert_eq!(fra, F::new(1u32, 42u32));

Comparison

use fraction::Fraction;

fn main () {
  let f14 = Fraction::new (1u64, 4u64); // 1/4 == 0.25
  let f12 = Fraction::new (1u64, 2u64); // 1/2 == 0.50
  let f24 = Fraction::new (2u64, 4u64); // 2/4 == 0.50
  let f34 = Fraction::new (3u64, 4u64); // 3/4 == 0.75

  assert_eq! (f12, f24);                   // 1/2 == 2/4
  assert_eq! (f34, f12 + f14);             // 3/4 == 1/2 + 1/4
  assert_eq! (f14, Fraction::from (0.25)); // 1/4 == 0.25
}

Change Log

Look into the CHANGELOG.md file for details

Dependencies

~0.3–1.8MB
~43K SLoC