Floats
A double is a binary fraction, so most decimals fall between two doubles: the
double nearest 0.1 is 0.1000000000000000055511151231257827…, and Rust reads and
writes it as 0.1 only because no shorter decimal is nearer to it. A decimal
converts to and from a double at the edges of a program, where a library, a
chart or a model speaks in floats, and each way says how it rounds.
To a Double
to_f64 gives the nearest double, a tie to the even
one: exact whenever the value is, and correctly rounded otherwise, as a decimal
read from text is, so it is the double Rust reads the decimal’s text as:
fn a_decimal_becomes_its_nearest_double() {
use ddust::{D64, D128, dec};
let tenth: D64<1> = dec!(0.1);
assert_eq!(tenth.to_f64().to_bits(), 0.1_f64.to_bits(), "the double Rust reads 0.1 as");
let long: D128<18> = dec!(0.123456789012345678);
assert_eq!(long.to_f64().to_string(), "0.12345678901234568", "correctly rounded");
}
From a Double
from_f64 takes the double’s exact binary value to
the nearest step at a scale by a rounding mode, or returns None for NaN, an
infinity, or a value past the range:
fn a_double_becomes_a_decimal_by_a_mode() {
use ddust::round::{Ceil, HalfEven};
use ddust::{D64, Fixed, dec};
let price = D64::from_f64(0.1, Fixed::<2>, HalfEven);
assert_eq!(price, Some(dec!(0.10)), "the nearest cent");
let up = D64::from_f64(0.1, Fixed::<2>, Ceil);
assert_eq!(up, Some(dec!(0.11)), "0.1000000000000000055…, up to the cent");
assert_eq!(D64::from_f64(f64::NAN, Fixed::<2>, HalfEven), None);
assert_eq!(D64::from_f64(1e17, Fixed::<2>, HalfEven), None, "past the range");
}
Rounded half to even, the nearest step of a double is the decimal it was written
from, while the steps stay below : the double 0.1 is 0.10 at two
decimals. A directed mode sees the double’s binary digits past the decimal ones:
rounded up by Ceil, the double 0.1 is 0.11 at two decimals.
from_f64 is a const fn. Serialization reads and writes a
decimal as a double through ddust::serde::float, and num-traits’
FromPrimitive reads one, both at the nearest step, a tie to the even one.