const SI_LABELS: &str = "afpnum KMGTPE";
const SI_SPACE: usize = 6;
const TEN: f64 = 10.0;
pub fn round_to_precision(n: f64, digits: usize) -> f64 {
if n == 0.0 {
return n;
}
let scale = digits as f64 - n.log10().floor() - 1.0;
(n * TEN.powf(scale)).round() * TEN.powf(-scale)
}
pub fn to_si(mut n: f64, base: f64) -> String {
let mut index = SI_SPACE;
while n >= base && index < SI_LABELS.len() - 1 {
n /= base;
index += 1;
}
while n < 1.0 && n != 0.0 && index > 0 {
n *= base;
index -= 1;
}
if index == SI_SPACE {
return format!("{n}");
}
let rounded_n = n.round();
let s = if rounded_n < 10.0 {
format!("{:.2}", round_to_precision(n, 3))
} else if rounded_n < 100.0 {
format!("{:.1}", round_to_precision(n, 3))
} else {
format!("{rounded_n}")
};
s + &SI_LABELS[index .. index + 1]
}
pub fn to_binary_si(n: f64) -> String {
to_si(n, 1024.0)
}
#[cfg(test)]
mod test {
use super::to_binary_si;
#[test]
fn test_to_si() {
assert_eq!(to_binary_si(0.0), "0");
assert_eq!(to_binary_si(1245.0), "1.22K");
assert_eq!(to_binary_si(12456.0), "12.2K");
}
}