rok_utils/data/
numbers.rs1pub fn format_number(n: f64, decimals: usize, sep: char) -> String {
2 let s = format!("{:.*}", decimals, n);
3 let parts: Vec<&str> = s.split('.').collect();
4 let int_part = parts[0];
5 let mut out = String::new();
6 for (count, c) in int_part.chars().rev().enumerate() {
7 if count > 0 && count % 3 == 0 {
8 out.insert(0, sep);
9 }
10 out.insert(0, c);
11 }
12 if parts.len() > 1 {
13 out.push('.');
14 out.push_str(parts[1]);
15 }
16 out
17}
18
19pub fn format_currency(amount: f64, currency: &str) -> String {
20 format!("{:.2}{}", amount, currency)
21}
22
23pub fn format_percentage(ratio: f64, _decimals: usize) -> String {
24 format!("{:.2}%", ratio * 100.0)
25}
26
27pub fn round(n: f64, decimals: u32) -> f64 {
28 let m = 10f64.powi(decimals as i32);
29 (n * m).round() / m
30}
31
32pub fn ceil(n: f64, decimals: u32) -> f64 {
33 let m = 10f64.powi(decimals as i32);
34 (n * m).ceil() / m
35}
36
37pub fn floor(n: f64, decimals: u32) -> f64 {
38 let m = 10f64.powi(decimals as i32);
39 (n * m).floor() / m
40}
41
42pub fn clamp(n: f64, min: f64, max: f64) -> f64 {
43 if n < min {
44 min
45 } else if n > max {
46 max
47 } else {
48 n
49 }
50}
51
52pub fn lerp(a: f64, b: f64, t: f64) -> f64 {
53 a + (b - a) * t
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn test_format_number() {
62 assert_eq!(format_number(1234.567, 2, ','), "1,234.57");
63 }
64
65 #[test]
66 fn test_round_ceiling_floor() {
67 assert_eq!(round(1.234, 2), 1.23);
68 assert_eq!(ceil(1.234, 2), 1.24);
69 assert_eq!(floor(1.234, 2), 1.23);
70 }
71
72 #[test]
73 fn test_clamp() {
74 assert_eq!(clamp(5.0, 0.0, 10.0), 5.0);
75 assert_eq!(clamp(-1.0, 0.0, 10.0), 0.0);
76 assert_eq!(clamp(15.0, 0.0, 10.0), 10.0);
77 }
78
79 #[test]
80 fn test_lerp() {
81 assert_eq!(lerp(0.0, 10.0, 0.5), 5.0);
82 }
83}