f64_fixed/
lib.rs

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