diff --git a/Cargo.lock b/Cargo.lock index 06e3f87..7e057b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -127,7 +127,7 @@ dependencies = [ [[package]] name = "rpn_rs" -version = "0.1.0" +version = "0.2.0" dependencies = [ "confy", "serde", diff --git a/src/main.rs b/src/main.rs index ad5dfdf..0221937 100644 --- a/src/main.rs +++ b/src/main.rs @@ -410,7 +410,7 @@ fn fmt_scientific(f: f64, precision: usize) -> String { fn fmt_engineering(f: f64, precision: usize) -> String { // Format the string so the first digit is always in the first column, and remove '.'. Requested precision + 2 to account for using 1, 2, or 3 digits for the whole portion of the string // 1,000 => 1000E3 - let all = format!("{:.precision$E}", f, precision = precision + 2).replacen(".", "", 1); + let all = format!(" {:.precision$E}", f, precision = precision + 2).replacen(".", "", 1); // Extract mantissa and the string representation of the exponent. Unwrap should be safe as formatter will insert E // 1000E3 => (1000, E3) let (num_str, exp_str) = all.split_at(all.find('E').unwrap()); @@ -429,14 +429,23 @@ fn fmt_engineering(f: f64, precision: usize) -> String { let display_exp = (exp.div_euclid(3) * 3).abs(); // Number of whole digits. Always 1, 2, or 3 depending on exponent divisibility let num_whole_digits = exp.rem_euclid(3) as usize + 1; + + // If this is a negative number, strip off the added space, otherwise keep the space (and next digit) + let num_str = if let Some(_) = num_str.strip_prefix(" -") { + &num_str[1..] + } else { + num_str + }; + // Whole portion of number. Slice is safe because the num_whole_digits is always 3 and the num_str will always have length >= 3 since precision in all=2 (+original whole digit) // Original number is 1,000 => whole will be 1, if original is 0.01, whole will be 10 - let whole = &num_str[0..num_whole_digits]; + let whole = &num_str[0..(num_whole_digits + 1)]; // Decimal portion of the number. Sliced from the number of whole digits to the *requested* precision. Precision generated in all will be requested precision + 2 - let decimal = &num_str[num_whole_digits..(precision + num_whole_digits)]; + let decimal = &num_str[(num_whole_digits + 1)..(precision + num_whole_digits + 1)]; // Right align whole portion, always have decimal point format!( - "{: >3}.{} E{}{:0>pad$}", + "{: >4}.{} E{}{:0>pad$}", + // display_sign, whole, decimal, display_exp_sign, @@ -503,4 +512,22 @@ mod tests { assert_eq!(fmt_separated(f, c), s); } } + + #[test] + fn test_fmt_engineering() { + for (f, c, s) in vec![ + (100.0, 3, " 100.000 E+00"), + (100.0, 3, " 100.000 E+00"), + (-100.0, 3, "-100.000 E+00"), + (100.0, 0, " 100. E+00"), + (-100.0, 0, "-100. E+00"), + (0.1, 2, " 100.00 E-03"), + (0.01, 2, " 10.00 E-03"), + (0.001, 2, " 1.00 E-03"), + (0.0001, 2, " 100.00 E-06"), + // Rounding + ] { + assert_eq!(fmt_engineering(f, c), s); + } + } }