1pub fn fmt_f64(f: f64) -> String {
21 format!("{f}")
22}
23
24#[cfg(test)]
25mod tests {
26 use super::fmt_f64;
27
28 #[test]
29 fn shortest_roundtrip_division() {
30 assert_eq!(fmt_f64(1.0 / 3.0), "0.3333333333333333");
31 }
32
33 #[test]
34 fn tiny_nonzero_is_never_zero_and_never_scientific() {
35 assert_eq!(fmt_f64(0.0000001), "0.0000001");
36 }
37
38 #[test]
39 fn typed_pi_echoes() {
40 assert_eq!(fmt_f64(3.141592653589793), "3.141592653589793");
41 }
42
43 #[test]
44 fn float_artifact_is_visible() {
45 assert_eq!(fmt_f64(0.1 + 0.2), "0.30000000000000004");
46 }
47
48 #[test]
49 fn integral_floats_stay_bare() {
50 assert_eq!(fmt_f64(2.0), "2");
51 assert_eq!(fmt_f64(100.0), "100");
52 assert_eq!(fmt_f64(-3.0), "-3");
53 }
54
55 #[test]
56 fn short_floats_unchanged() {
57 assert_eq!(fmt_f64(1.5), "1.5");
58 assert_eq!(fmt_f64(0.5), "0.5");
59 assert_eq!(fmt_f64(-1.5), "-1.5");
60 }
61
62 #[test]
63 fn non_finite_values() {
64 assert_eq!(fmt_f64(f64::NAN), "NaN");
65 assert_eq!(fmt_f64(f64::INFINITY), "inf");
66 assert_eq!(fmt_f64(f64::NEG_INFINITY), "-inf");
67 }
68
69 #[test]
70 fn negative_zero_keeps_its_sign() {
71 assert_eq!(fmt_f64(-0.0), "-0");
72 assert_eq!(fmt_f64(0.0), "0");
73 }
74
75 #[test]
76 fn huge_magnitudes_never_go_scientific() {
77 let s = fmt_f64(1e300);
78 assert!(!s.contains('e') && !s.contains('E'), "scientific leaked: {s}");
79 assert_eq!(s.len(), 301);
80 assert!(s.starts_with('1'));
81 let s = fmt_f64(f64::MAX);
82 assert!(!s.contains('e') && !s.contains('E'), "scientific leaked: {s}");
83 }
84
85 #[test]
86 fn subnormals_never_go_scientific() {
87 let s = fmt_f64(5e-324);
88 assert!(!s.contains('e') && !s.contains('E'), "scientific leaked: {s}");
89 assert!(s.starts_with("0.000"));
90 }
91
92 #[test]
95 fn worst_case_width_fits_wasm_scratch() {
96 for f in [5e-324, -5e-324, f64::MAX, f64::MIN, 1e300, -1e300] {
97 let s = fmt_f64(f);
98 assert!(s.len() <= 340, "{} bytes for {f:e}", s.len());
99 }
100 }
101
102 #[test]
104 fn output_roundtrips_bit_exactly() {
105 for f in [
106 1.0 / 3.0,
107 0.1 + 0.2,
108 3.141592653589793,
109 0.0000001,
110 -0.0,
111 1e300,
112 5e-324,
113 f64::MAX,
114 f64::MIN_POSITIVE,
115 123456789.123456789,
116 ] {
117 let parsed: f64 = fmt_f64(f).parse().unwrap();
118 assert_eq!(parsed.to_bits(), f.to_bits(), "round-trip drift for {f:e}");
119 }
120 }
121}