Add engineering format mode
This commit is contained in:
parent
1ccc950afe
commit
73b7571030
76
src/main.rs
76
src/main.rs
@ -403,62 +403,42 @@ fn fmt_scientific(f: f64, precision: usize) -> String {
|
|||||||
let sign = if !ret.starts_with('-') { " " } else { "" };
|
let sign = if !ret.starts_with('-') { " " } else { "" };
|
||||||
format!("{}{}E{}{:0>pad$}", sign, ret, exp_sign, exp, pad = 2)
|
format!("{}{}E{}{:0>pad$}", sign, ret, exp_sign, exp, pad = 2)
|
||||||
}
|
}
|
||||||
// (a)E(c)
|
|
||||||
// E power = f.log10().div_euclid(3) * 3
|
|
||||||
// left portion = f.log10().rem_euclid(3) + 1
|
|
||||||
// .0001 - 100E-6 - 1E-4
|
|
||||||
// .001 - 1E-3 - 1E-3 => -3
|
|
||||||
// .01 - 10E-3 - 1E-2
|
|
||||||
// .1 - 100E-3 - 1E-1
|
|
||||||
// 1 - 1E+0 - 1E+0 => 0
|
|
||||||
// 10 - 10E+0 - 1E+1
|
|
||||||
// 100 - 100E+0 - 1E+2
|
|
||||||
// 1000 - 1E+3 - 1E+3 => 3
|
|
||||||
// 10000 - 10E+3 - 1E+4
|
|
||||||
|
|
||||||
// fn fmt_engineering(i: usize, f: f64, precision: usize) -> String {
|
|
||||||
// // TODO: There is probably a more efficent way to do this using slices or something
|
|
||||||
// let mut all = format!("{:.precision$e}", f, precision = precision + 2).replacen(".", "", 1);
|
|
||||||
// // The left 1, 2, or 3 digits
|
|
||||||
// let left = all.split_off(f.log10().rem_euclid(3) + 1);
|
|
||||||
// // The length of ret will always be at least 5 -- 2 leading spaces, integer portion, and precision + 2
|
|
||||||
// let exp = ret.split_off(ret.find('E').unwrap_or(0));
|
|
||||||
// let left = ret[()..()]
|
|
||||||
// let first_three = match exp {
|
|
||||||
// }
|
|
||||||
// let (pow_sign, exp) = if exp.starts_with("E-") {
|
|
||||||
// ('-', &exp[2..])
|
|
||||||
// } else {
|
|
||||||
// ('+', &exp[1..])
|
|
||||||
// };
|
|
||||||
// let sign = if !ret.starts_with('-') { " " } else { "" };
|
|
||||||
// format!(
|
|
||||||
// "{:>2}: {}{}e{}{:0>pad$}",
|
|
||||||
// i,
|
|
||||||
// sign,
|
|
||||||
// ret,
|
|
||||||
// pow_sign,
|
|
||||||
// exp,
|
|
||||||
// pad = 2
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn fmt_engineering(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);
|
||||||
let (mantissa_str, pow_str) = all.split_at(all.find('E').unwrap_or(0));
|
// Extract mantissa and the string representation of the exponent. Unwrap should be safe as formatter will insert E
|
||||||
let pow = pow_str[1..].parse::<isize>().unwrap();
|
// 1000E3 => (1000, E3)
|
||||||
let display_pow_sign = if let Some(stripped) = pow_str.strip_prefix("E-") {
|
let (num_str, exp_str) = all.split_at(all.find('E').unwrap());
|
||||||
|
// Extract the exponent as an isize. This should always be true because f64 max will be ~400
|
||||||
|
// E3 => 3 as isize
|
||||||
|
let exp = exp_str[1..].parse::<isize>().unwrap();
|
||||||
|
// Sign of the exponent. If string representation starts with E-, then negative
|
||||||
|
let display_exp_sign = if let Some(stripped) = exp_str.strip_prefix("E-") {
|
||||||
'-'
|
'-'
|
||||||
} else {
|
} else {
|
||||||
'+'
|
'+'
|
||||||
};
|
};
|
||||||
let display_pow = (pow.div_euclid(3) * 3).abs();
|
|
||||||
let num_digits = pow.rem_euclid(3) as usize + 1;
|
// The exponent to display. Always a multiple of 3 in engineering mode. Always positive because sign is added with display_exp_sign above
|
||||||
let whole = &mantissa_str[0..num_digits];
|
// 100 => 0, 1000 => 3, .1 => 3 (but will show as -3)
|
||||||
let decimal = &mantissa_str[num_digits..];
|
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;
|
||||||
|
// 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];
|
||||||
|
// 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)];
|
||||||
|
// Right align whole portion, always have decimal point
|
||||||
format!(
|
format!(
|
||||||
"{: >3}.{} * 10 ^ {}{}",
|
"{: >3}.{} E{}{:0>pad$}",
|
||||||
whole, decimal, display_pow_sign, display_pow
|
whole,
|
||||||
|
decimal,
|
||||||
|
display_exp_sign,
|
||||||
|
display_exp,
|
||||||
|
pad = 2
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user