Skip to main content

v_utils/utils/
format.rs

1#[macro_export]
2macro_rules! fmt_with_width {
3	($f:expr, $s:expr) => {{
4		if $f.fill() != ' ' && $f.fill() != '\0' {
5			unimplemented!("Specifying fill is not supported. Rust is letting us down, impossible to implement, call `to_string()` and use its implementation.");
6		}
7		if let Some(w) = $f.width() {
8			match $f.align() {
9				Some(std::fmt::Alignment::Left) => write!($f, "{:<width$}", $s, width = w),
10				Some(std::fmt::Alignment::Right) => write!($f, "{:>width$}", $s, width = w),
11				Some(std::fmt::Alignment::Center) => write!($f, "{:^width$}", $s, width = w),
12				_ => write!($f, "{:width$}", $s, width = w),
13			}
14		} else {
15			write!($f, "{}", $s)
16		}
17	}};
18}
19
20/// formats _up to_ specified number of significant digits
21///```rust
22/// use v_utils::utils::format_significant_digits;
23/// assert_eq!(format_significant_digits(0.000123456789, 3), "0.000123");
24///```
25pub fn format_significant_digits(n: f64, sig_digits: usize) -> String {
26	if n == 0.0 {
27		return "0".to_string();
28	}
29
30	let full = format!("{:.12}", n.abs());
31	if !full.contains('.') {
32		return format!("{n:.1}");
33	}
34
35	let first_sig = full.chars().position(|c| c != '0' && c != '.').unwrap_or(0);
36
37	let mut sig_count = 0;
38	let mut last_pos = full.len();
39	for (i, c) in full.chars().enumerate().skip(first_sig) {
40		if c != '.' {
41			sig_count += 1;
42			if sig_count == sig_digits {
43				last_pos = i + 1;
44				break;
45			}
46		}
47	}
48
49	let precision = full[..last_pos].split('.').nth(1).unwrap_or("").len();
50	format!("{:.*}", precision, n)
51}