pub fn format_number(value: f64) -> String {
let abs = value.abs();
let (formatted, suffix) = if abs >= 1_000_000_000.0 {
(value / 1_000_000_000.0, "B")
} else if abs >= 1_000_000.0 {
(value / 1_000_000.0, "M")
} else if abs >= 1_000.0 {
(value / 1_000.0, "K")
} else {
(value, "")
};
if suffix.is_empty() {
if abs == 0.0 {
"0".to_string()
} else if abs < 0.01 {
format!("{:.4}", formatted)
} else if abs < 1.0 {
format!("{:.2}", formatted)
} else if formatted.fract() == 0.0 {
format!("{:.0}", formatted)
} else {
format!("{:.2}", formatted)
}
} else {
format!("{:.2}{}", formatted, suffix)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_format_billions() {
assert_eq!(format_number(1_234_567_890.0), "1.23B");
assert_eq!(format_number(5_000_000_000.0), "5.00B");
}
#[test]
fn should_format_millions() {
assert_eq!(format_number(1_234_567.0), "1.23M");
assert_eq!(format_number(5_500_000.0), "5.50M");
}
#[test]
fn should_format_thousands() {
assert_eq!(format_number(1_234.0), "1.23K");
assert_eq!(format_number(52_647.0), "52.65K");
}
#[test]
fn should_format_whole_numbers() {
assert_eq!(format_number(42.0), "42");
assert_eq!(format_number(100.0), "100");
}
#[test]
fn should_format_decimals() {
assert_eq!(format_number(42.5), "42.50");
assert_eq!(format_number(0.75), "0.75");
}
#[test]
fn should_format_small_decimals() {
assert_eq!(format_number(0.005), "0.0050");
assert_eq!(format_number(0.0001), "0.0001");
}
#[test]
fn should_handle_zero() {
assert_eq!(format_number(0.0), "0");
}
#[test]
fn should_handle_negative_numbers() {
assert_eq!(format_number(-1_500.0), "-1.50K");
assert_eq!(format_number(-42.5), "-42.50");
}
}