Skip to content

Commit 9bd438c

Browse files
committed
Add pretty printing helper function
1 parent c0614af commit 9bd438c

File tree

3 files changed

+107
-2
lines changed

3 files changed

+107
-2
lines changed

src/data/float.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// The code that is related to float number handling
2+
3+
fn find_minimal_repr(n: f64, eps: f64) -> (f64, usize) {
4+
if eps >= 1.0 {
5+
return (n, 0);
6+
}
7+
if n - n.floor() < eps {
8+
(n.floor(), 0)
9+
} else if n.ceil() - n < eps {
10+
(n.ceil(), 0)
11+
} else {
12+
let (rem, pre) = find_minimal_repr((n - n.floor()) * 10.0, eps * 10.0);
13+
(n.floor() + rem / 10.0, pre + 1)
14+
}
15+
}
16+
17+
fn float_to_string(n: f64, max_precision: usize) -> String {
18+
let (sign, n) = if n < 0.0 { ("-", -n) } else { ("", n) };
19+
let int_part = n.floor();
20+
21+
let dec_part =
22+
((n.abs() - int_part.abs()) * (10.0f64).powf(max_precision as f64)).round() as u64;
23+
24+
if dec_part == 0 || max_precision == 0 {
25+
return format!("{}{:.0}", sign, int_part);
26+
}
27+
28+
let mut leading = "".to_string();
29+
let mut dec_result = format!("{}", dec_part);
30+
31+
for _ in 0..(max_precision - dec_result.len()) {
32+
leading.push('0');
33+
}
34+
35+
while let Some(c) = dec_result.pop() {
36+
if c != '0' {
37+
dec_result.push(c);
38+
break;
39+
}
40+
}
41+
42+
format!("{}{:.0}.{}{}", sign, int_part, leading, dec_result)
43+
}
44+
45+
/// The function that pretty prints the floating number
46+
/// Since rust doesn't have anything that can format a float with out appearance, so we just
47+
/// implemnet a float pretty printing function, which finds the shortest representation of a
48+
/// floating point number within the allowed error range.
49+
///
50+
/// - `n`: The float number to pretty-print
51+
/// - `allow_sn`: Should we use scientific notation when possible
52+
/// - **returns**: The pretty printed string
53+
pub fn pretty_print_float(n: f64, allow_sn: bool) -> String {
54+
let (n, p) = find_minimal_repr(n, 1e-10);
55+
let d_repr = float_to_string(n, p);
56+
if !allow_sn {
57+
d_repr
58+
} else {
59+
if n == 0.0 {
60+
return "0".to_string();
61+
}
62+
63+
let mut idx = n.abs().log10().floor();
64+
let mut exp = (10.0f64).powf(idx);
65+
66+
if n.abs() / exp + 1e-5 >= 10.0 {
67+
idx += 1.0;
68+
exp *= 10.0;
69+
}
70+
71+
if idx.abs() < 3.0 {
72+
return d_repr;
73+
}
74+
75+
let (sn, sp) = find_minimal_repr(n / exp, 1e-5);
76+
let s_repr = format!("{}e{}", float_to_string(sn, sp), float_to_string(idx, 0));
77+
if s_repr.len() + 1 < d_repr.len() {
78+
s_repr
79+
} else {
80+
d_repr
81+
}
82+
}
83+
}
84+
85+
#[cfg(test)]
86+
mod test {
87+
use super::*;
88+
#[test]
89+
fn test_pretty_printing() {
90+
assert_eq!(pretty_print_float(0.99999999999999999999, false), "1");
91+
assert_eq!(pretty_print_float(0.9999, false), "0.9999");
92+
assert_eq!(
93+
pretty_print_float(-1e-5 - 0.00000000000000001, true),
94+
"-1e-5"
95+
);
96+
assert_eq!(
97+
pretty_print_float(-1e-5 - 0.00000000000000001, false),
98+
"-0.00001"
99+
);
100+
assert_eq!(pretty_print_float(1e100, true), "1e100");
101+
assert_eq!(pretty_print_float(1234567890f64, true), "1234567890");
102+
assert_eq!(pretty_print_float(1000000001f64, true), "1e9");
103+
}
104+
}

src/data/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ pub use data_range::fitting_range;
88

99
mod quartiles;
1010
pub use quartiles::Quartiles;
11+
12+
pub mod float;

src/element/text.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,7 @@ fn layout_multiline_text<'a, F: FnMut(&'a str)>(
131131
while !remaining.is_empty() {
132132
let mut left = 0;
133133
while left < remaining.len() {
134-
let width =
135-
font.box_size(&remaining[0..=left]).unwrap_or((0, 0)).0 as i32;
134+
let width = font.box_size(&remaining[0..=left]).unwrap_or((0, 0)).0 as i32;
136135

137136
if width > max_width as i32 {
138137
break;

0 commit comments

Comments
 (0)