1use core::fmt::{Display, Formatter};
10extern crate alloc;
11#[allow(unused_imports)]
12use crate::f64::FloatExt;
13use alloc::string::String;
14
15#[macro_export]
18macro_rules! format {
19 ($($arg:tt)*) => {{
20 extern crate alloc;
21 use alloc::string::String;
22 use core::fmt::Write;
23
24 let mut val = String::new();
25 val.write_fmt(format_args!($($arg)*)).expect("a formatting trait implementation returned an error");
26 val
27 }};
28}
29
30pub struct DecimalFormatF64(pub usize, pub usize, pub f64);
47
48impl Display for DecimalFormatF64 {
49 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
50 let mut base = self.2.trunc();
51 let width = self.0;
52 let prec = self.1;
53 let powi = 10_u64.pow(self.1 as u32) as f64;
54 let mut val = (self.2.fract().abs() * powi).round();
55 if val >= powi {
56 base += 1.;
57 val -= powi;
58 }
59 let val = val as u64;
60 write!(f, "{base:0width$}.{val:0prec$}")
61 }
62}
63
64pub struct DecimalFormatF32(pub usize, pub usize, pub f32);
81
82impl Display for DecimalFormatF32 {
83 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
84 let mut base = self.2.trunc();
85 let width = self.0;
86 let prec = self.1;
87 let powi = 10_u64.pow(self.1 as u32) as f32;
88 let mut val = (self.2.fract().abs() * powi).round();
89 if val >= powi {
90 base += 1.;
91 val -= powi;
92 }
93 let val = val as u64;
94 write!(f, "{base:0width$}.{val:0prec$}")
95 }
96}
97
98pub struct DecimalFormat {
117 width: usize,
118 precision: usize,
119}
120
121impl DecimalFormat {
122 pub fn new(width: usize, precision: usize) -> Self {
123 Self { width, precision }
124 }
125
126 pub fn format_f64(&self, val: f64) -> String {
137 format!("{}", DecimalFormatF64(self.width, self.precision, val))
138 }
139
140 pub fn format_f32(&self, val: f32) -> String {
151 format!("{}", DecimalFormatF32(self.width, self.precision, val))
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use crate::fmt::DecimalFormatF64;
158
159 #[test]
160 pub fn test() {
161 let val = 0.1234567;
162 assert_eq!("00.1235", format!("{}", DecimalFormatF64(2, 4, val)));
163
164 assert_eq!("0.123", format!("{}", DecimalFormatF64(0, 3, val)));
165 assert_eq!("0.123", format!("{}", DecimalFormatF64(1, 3, val)));
166 assert_eq!("00.123", format!("{}", DecimalFormatF64(2, 3, val)));
167 assert_eq!("00.12346", format!("{}", DecimalFormatF64(2, 5, val)));
168 assert_eq!("00.123457", format!("{}", DecimalFormatF64(2, 6, val)));
169 assert_eq!("00.1234567", format!("{}", DecimalFormatF64(2, 7, val)));
170 assert_eq!("00.12345670", format!("{}", DecimalFormatF64(2, 8, val)));
171 assert_eq!("00.123456700", format!("{}", DecimalFormatF64(2, 9, val)));
172 assert_eq!(
173 "000.1234567000",
174 format!("{}", DecimalFormatF64(3, 10, val))
175 );
176 }
177
178 #[test]
179 pub fn test2() {
180 assert_eq!("1.0", format!("{}", DecimalFormatF64(1, 0, 0.98)));
181 assert_eq!("1.0", format!("{}", DecimalFormatF64(1, 1, 0.98)));
182 assert_eq!("0.98", format!("{}", DecimalFormatF64(1, 2, 0.98)));
183 assert_eq!("0.980", format!("{}", DecimalFormatF64(1, 3, 0.98)));
184 assert_eq!("0.950", format!("{}", DecimalFormatF64(1, 3, 0.95)));
185 assert_eq!("0.940", format!("{}", DecimalFormatF64(1, 3, 0.94)));
186 assert_eq!("0.94", format!("{}", DecimalFormatF64(1, 2, 0.94)));
187 assert_eq!("0.9", format!("{}", DecimalFormatF64(1, 1, 0.94)));
188 assert_eq!("1.0", format!("{}", DecimalFormatF64(1, 0, 0.94)));
189
190 assert_eq!("0.999", format!("{}", DecimalFormatF64(1, 3, 0.999)));
191 assert_eq!("0.9990", format!("{}", DecimalFormatF64(1, 4, 0.999)));
192 assert_eq!("1.00", format!("{}", DecimalFormatF64(1, 2, 0.999)));
193
194 assert_eq!("-21.30", format!("{}", DecimalFormatF64(2, 2, -21.3)));
195 assert_eq!("-21.3", format!("{}", DecimalFormatF64(2, 1, -21.3)));
196 assert_eq!("-21.0", format!("{}", DecimalFormatF64(2, 0, -21.3)));
197 }
198}