Skip to main content

f64_fixed/
lib.rs

1pub trait ToFixedString {
2    fn to_fixed_string(&self, places: isize) -> String;
3}
4
5impl ToFixedString for f64 {
6    fn to_fixed_string(&self, places: isize) -> String {
7        let align_left = places > 0;
8        let places = places.abs().max(6) as usize;
9        let sign = if self.is_sign_negative() { "-" } else { "" };
10        let value = self.abs();
11
12        let (mut mantissa, exp) = if *self == 0.0 {
13            ("0.0".to_string(), "".to_string())
14        } else {
15            let exp = self.abs().log10().floor() as i32 / 3 * 3;
16            if exp > 3 || exp < -3 || value < 0.001 {
17                (format!("{:.6}", value / 10f64.powi(exp)), format!("{:+}", exp))
18            } else {
19                (format!("{:.6}", value), "".to_string())
20            }
21        };
22
23        let mantissa_places = places.saturating_sub(sign.len() + exp.len());
24        if let Some(pos) = mantissa.find('.') {
25            if mantissa_places == pos {
26                mantissa.truncate(pos);
27            } else if mantissa_places > pos {
28                mantissa.truncate(mantissa_places);
29                mantissa = mantissa.trim_end_matches('0').trim_end_matches('.').to_string();
30            }
31        }
32
33        if align_left {
34            format!("{}{}{}{}", sign, mantissa, exp, " ".repeat(mantissa_places.saturating_sub(mantissa.len())))
35        } else {
36            format!("{}{}{}{}", " ".repeat(mantissa_places.saturating_sub(mantissa.len())), sign, mantissa, exp)
37        }
38    }
39}
40
41pub fn to_fixed_string(value: f64, places: isize) -> String {
42    value.to_fixed_string(places)
43}