I have ah x: i64 that is representing a value x as real / 65536.0 (fixed point with 16 bits of decimal)
Is there an easy way to print this ? x as f64 / 65536.0 loses precision, and I'd prefer to not roll manual routines for handling integral / fractional parts
use std::fmt;
const BITS: u8 = 16;
const SCALE: i64 = 1 << BITS;
struct Fixed(i64);
impl fmt::Display for Fixed {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let integer_part = self.0 / SCALE;
let fractional_part = (self.0 % SCALE).abs();
// The fractional part is already multiplied by 2^BITS.
// If we additionally multiply by 5^BITS, then it is now
// multiplied by 10^BITS, so if we put it BITS decimal places
// to the right, it will have the correct place value.
let mut decimal_fraction = fractional_part * 5i64.pow(BITS.into());
// But we don't want to print extraneous zeros, so figure
// out how many places we actually need and adjust the value.
let mut places: usize = BITS.into();
while decimal_fraction % 10 == 0 && places > 1 {
decimal_fraction /= 10;
places -= 1;
}
write!(f, "{integer_part}.{decimal_fraction:0places$}")
}
}
#[test]
fn test() {
assert_eq!(Fixed(0).to_string(), "0.0");
assert_eq!(Fixed(SCALE * 70).to_string(), "70.0");
assert_eq!(Fixed(SCALE * 15 / 10).to_string(), "1.5");
assert_eq!(Fixed(-(SCALE * 15 / 10)).to_string(), "-1.5");
assert_eq!(Fixed(SCALE * 123125 / 1000).to_string(), "123.125");
}