@@ -36,42 +36,26 @@ pub fn escape_pango_text(text: String) -> String {
36
36
. collect ( )
37
37
}
38
38
39
- pub fn format_number ( raw_value : f64 , total_digits : usize , min_unit : & str , suffix : & str ) -> String {
40
- let ( min_unit_value, min_unit_level) = match min_unit {
41
- "T" => ( raw_value / 1_000_000_000_000.0 , 4 ) ,
42
- "G" => ( raw_value / 1_000_000_000.0 , 3 ) ,
43
- "M" => ( raw_value / 1_000_000.0 , 2 ) ,
44
- "K" => ( raw_value / 1_000.0 , 1 ) ,
45
- "1" => ( raw_value, 0 ) ,
46
- "m" => ( raw_value * 1_000.0 , -1 ) ,
47
- "u" => ( raw_value * 1_000_000.0 , -2 ) ,
48
- "n" => ( raw_value * 1_000_000_000.0 , -3 ) ,
49
- _ => ( raw_value * 1_000_000_000_000.0 , -4 ) ,
39
+ /// Format `raw_value` to engineering notation
40
+ pub fn format_number ( raw_value : f64 , total_digits : usize , min_suffix : & str , unit : & str ) -> String {
41
+ let min_exp_level = match min_suffix {
42
+ "T" => 4 ,
43
+ "G" => 3 ,
44
+ "M" => 2 ,
45
+ "K" => 1 ,
46
+ "1" => 0 ,
47
+ "m" => -1 ,
48
+ "u" => -2 ,
49
+ "n" => -3 ,
50
+ _ => -4 ,
50
51
} ;
51
52
52
- //println!("Min Unit: ({}, {})", min_unit_value, min_unit_level);
53
-
54
- let ( magnitude_value, magnitude_level) = match raw_value {
55
- x if x >= 100_000_000_000.0 => ( raw_value / 1_000_000_000_000.0 , 4 ) ,
56
- x if x >= 100_000_000.0 => ( raw_value / 1_000_000_000.0 , 3 ) ,
57
- x if x >= 100_000.0 => ( raw_value / 1_000_000.0 , 2 ) ,
58
- x if x >= 100.0 => ( raw_value / 1_000.0 , 1 ) ,
59
- x if x >= 0.1 => ( raw_value, 0 ) ,
60
- x if x >= 0.000_1 => ( raw_value * 1_000.0 , -1 ) ,
61
- x if x >= 0.000_000_1 => ( raw_value * 1_000_000.0 , -2 ) ,
62
- x if x >= 0.000_000_000_1 => ( raw_value * 1_000_000_000.0 , -3 ) ,
63
- _ => ( raw_value * 1_000_000_000_000.0 , -4 ) ,
64
- } ;
65
-
66
- //println!("Magnitude: ({}, {})", magnitude_value, magnitude_level);
67
-
68
- let ( value, level) = if magnitude_level < min_unit_level {
69
- ( min_unit_value, min_unit_level)
70
- } else {
71
- ( magnitude_value, magnitude_level)
72
- } ;
53
+ let exp_level = ( raw_value. log10 ( ) . div_euclid ( 3. ) as i32 )
54
+ . max ( min_exp_level)
55
+ . min ( 4 ) ;
56
+ let value = raw_value / ( 10f64 ) . powi ( exp_level * 3 ) ;
73
57
74
- let unit = match level {
58
+ let suffix = match exp_level {
75
59
4 => "T" ,
76
60
3 => "G" ,
77
61
2 => "M" ,
@@ -83,14 +67,17 @@ pub fn format_number(raw_value: f64, total_digits: usize, min_unit: &str, suffix
83
67
_ => "p" ,
84
68
} ;
85
69
86
- let _decimal_precision = total_digits as i16 - if value >= 10.0 { 2 } else { 1 } ;
87
- let decimal_precision = if _decimal_precision < 0 {
88
- 0
70
+ let total_digits = total_digits as isize ;
71
+ let decimals = ( if value >= 100. {
72
+ total_digits - 3
73
+ } else if value >= 10. {
74
+ total_digits - 2
89
75
} else {
90
- _decimal_precision
91
- } ;
76
+ total_digits - 1
77
+ } )
78
+ . max ( 0 ) ;
92
79
93
- format ! ( "{:.*}{}{}" , decimal_precision as usize , value, unit , suffix )
80
+ format ! ( "{:.*}{}{}" , decimals as usize , value, suffix , unit )
94
81
}
95
82
96
83
pub fn battery_level_to_icon ( charge_level : Result < u64 > ) -> & ' static str {
@@ -512,7 +499,18 @@ macro_rules! if_debug {
512
499
513
500
#[ cfg( test) ]
514
501
mod tests {
515
- use crate :: util:: { color_from_rgba, has_command} ;
502
+ use crate :: util:: { color_from_rgba, format_number, has_command} ;
503
+
504
+ #[ test]
505
+ fn test_format_number ( ) {
506
+ assert_eq ! ( format_number( 1.0 , 3 , "" , "s" ) , "1.00s" ) ;
507
+ assert_eq ! ( format_number( 1.007 , 3 , "" , "s" ) , "1.01s" ) ;
508
+ assert_eq ! ( format_number( 1.007 , 4 , "K" , "s" ) , "0.001Ks" ) ;
509
+ assert_eq ! ( format_number( 1007. , 3 , "K" , "s" ) , "1.01Ks" ) ;
510
+ assert_eq ! ( format_number( 107_000. , 3 , "" , "s" ) , "107Ks" ) ;
511
+ assert_eq ! ( format_number( 107. , 3 , "" , "s" ) , "107s" ) ;
512
+ assert_eq ! ( format_number( 0.000_123_123 , 3 , "" , "N" ) , "123uN" ) ;
513
+ }
516
514
517
515
#[ test]
518
516
// we assume sh is always available
0 commit comments