Start work on engineering display mode
This commit is contained in:
parent
61fa6ee530
commit
1ccc950afe
@ -85,7 +85,7 @@ impl fmt::Display for CalculatorDisplayMode {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
CalculatorDisplayMode::Default => write!(f, "DEF"),
|
CalculatorDisplayMode::Default => write!(f, "DEF"),
|
||||||
CalculatorDisplayMode::Separated(c) => write!(f, "DEF({})", c),
|
CalculatorDisplayMode::Separated(c) => write!(f, "SEP({})", c),
|
||||||
CalculatorDisplayMode::Scientific(p) => write!(f, "SCI({})", p),
|
CalculatorDisplayMode::Scientific(p) => write!(f, "SCI({})", p),
|
||||||
CalculatorDisplayMode::Engineering(p) => write!(f, "ENG({})", p),
|
CalculatorDisplayMode::Engineering(p) => write!(f, "ENG({})", p),
|
||||||
CalculatorDisplayMode::Fixed(p) => write!(f, "FIX({})", p),
|
CalculatorDisplayMode::Fixed(p) => write!(f, "FIX({})", p),
|
||||||
|
129
src/main.rs
129
src/main.rs
@ -119,12 +119,14 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
let content = vec![Spans::from(Span::raw(
|
let content = vec![Spans::from(Span::raw(
|
||||||
match app.calculator.get_display_mode() {
|
match app.calculator.get_display_mode() {
|
||||||
CalculatorDisplayMode::Default => format!("{:>2}: {}", i, *m),
|
CalculatorDisplayMode::Default => format!("{:>2}: {}", i, *m),
|
||||||
CalculatorDisplayMode::Separated(c) => fmt_separated(i, *m, *c),
|
CalculatorDisplayMode::Separated(c) => {
|
||||||
CalculatorDisplayMode::Scientific(precision) => {
|
format!("{:>2}: {}", i, fmt_separated(*m, *c))
|
||||||
fmt_scientific(i, *m, *precision)
|
|
||||||
}
|
}
|
||||||
CalculatorDisplayMode::Engineering(_precision) => {
|
CalculatorDisplayMode::Scientific(precision) => {
|
||||||
format!("{:>2}: {}", i, m)
|
format!("{:>2}: {}", i, fmt_scientific(*m, *precision))
|
||||||
|
}
|
||||||
|
CalculatorDisplayMode::Engineering(precision) => {
|
||||||
|
format!("{:>2}: {}", i, fmt_engineering(*m, *precision))
|
||||||
}
|
}
|
||||||
CalculatorDisplayMode::Fixed(precision) => {
|
CalculatorDisplayMode::Fixed(precision) => {
|
||||||
format!("{:>2}: {:.precision$}", i, m, precision = precision)
|
format!("{:>2}: {:.precision$}", i, m, precision = precision)
|
||||||
@ -389,30 +391,36 @@ fn draw_clippy_rect<T: std::io::Write>(c: ClippyRectangle, f: &mut Frame<Termion
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Based on https://stackoverflow.com/a/65266882
|
// Based on https://stackoverflow.com/a/65266882
|
||||||
fn fmt_scientific(i: usize, f: f64, precision: usize) -> String {
|
fn fmt_scientific(f: f64, precision: usize) -> String {
|
||||||
let mut ret = format!("{:.precision$E}", f, precision = precision);
|
let mut ret = format!("{:.precision$E}", f, precision = precision);
|
||||||
let exp = ret.split_off(ret.find('E').unwrap_or(0));
|
let exp = ret.split_off(ret.find('E').unwrap_or(0));
|
||||||
let (pow_sign, exp) = if let Some(stripped) = exp.strip_prefix("E-") {
|
let (exp_sign, exp) = if let Some(stripped) = exp.strip_prefix("E-") {
|
||||||
('-', stripped)
|
('-', stripped)
|
||||||
} else {
|
} else {
|
||||||
('+', &exp[1..])
|
('+', &exp[1..])
|
||||||
};
|
};
|
||||||
|
|
||||||
let sign = if !ret.starts_with('-') { " " } else { "" };
|
let sign = if !ret.starts_with('-') { " " } else { "" };
|
||||||
format!(
|
format!("{}{}E{}{:0>pad$}", sign, ret, exp_sign, exp, pad = 2)
|
||||||
"{:>2}: {}{}E{}{:0>pad$}",
|
|
||||||
i,
|
|
||||||
sign,
|
|
||||||
ret,
|
|
||||||
pow_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
|
||||||
|
|
||||||
// // 100 E+3
|
|
||||||
// fn fmt_engineering(i: usize, f: f64, precision: usize) -> String {
|
// fn fmt_engineering(i: usize, f: f64, precision: usize) -> String {
|
||||||
// let mut ret = format!(" {:.precision$e}", f, precision = precision + 2);
|
// // 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
|
// // 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 exp = ret.split_off(ret.find('E').unwrap_or(0));
|
||||||
// let left = ret[()..()]
|
// let left = ret[()..()]
|
||||||
@ -435,14 +443,33 @@ fn fmt_scientific(i: usize, f: f64, precision: usize) -> String {
|
|||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fn fmt_separated(i: usize, f: f64, sep: char) -> String {
|
fn fmt_engineering(f: f64, precision: usize) -> String {
|
||||||
|
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));
|
||||||
|
let pow = pow_str[1..].parse::<isize>().unwrap();
|
||||||
|
let display_pow_sign = if let Some(stripped) = pow_str.strip_prefix("E-") {
|
||||||
|
'-'
|
||||||
|
} else {
|
||||||
|
'+'
|
||||||
|
};
|
||||||
|
let display_pow = (pow.div_euclid(3) * 3).abs();
|
||||||
|
let num_digits = pow.rem_euclid(3) as usize + 1;
|
||||||
|
let whole = &mantissa_str[0..num_digits];
|
||||||
|
let decimal = &mantissa_str[num_digits..];
|
||||||
|
format!(
|
||||||
|
"{: >3}.{} * 10 ^ {}{}",
|
||||||
|
whole, decimal, display_pow_sign, display_pow
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fmt_separated(f: f64, sep: char) -> String {
|
||||||
let mut ret = f.to_string();
|
let mut ret = f.to_string();
|
||||||
let start = if ret.starts_with('-') { 1 } else { 0 };
|
let start = if ret.starts_with('-') { 1 } else { 0 };
|
||||||
let end = ret.find('.').unwrap_or_else(|| ret.len());
|
let end = ret.find('.').unwrap_or_else(|| ret.len());
|
||||||
for i in 0..((end - start - 1).div_euclid(3)) {
|
for i in 0..((end - start - 1).div_euclid(3)) {
|
||||||
ret.insert(end - (i + 1) * 3, sep);
|
ret.insert(end - (i + 1) * 3, sep);
|
||||||
}
|
}
|
||||||
format!("{:>2}: {}", i, ret)
|
format!("{}", ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -450,47 +477,47 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fmt_scientific() {
|
fn test_fmt_scientific() {
|
||||||
for (i, f, p, s) in vec![
|
for (f, p, s) in vec![
|
||||||
// Basic
|
// Basic
|
||||||
(0, 1.0, 0, " 0: 1E+00"),
|
(1.0, 0, " 1E+00"),
|
||||||
(0, -1.0, 0, " 0: -1E+00"),
|
(-1.0, 0, "-1E+00"),
|
||||||
(0, 100.0, 0, " 0: 1E+02"),
|
(100.0, 0, " 1E+02"),
|
||||||
(0, 0.1, 0, " 0: 1E-01"),
|
(0.1, 0, " 1E-01"),
|
||||||
(0, 0.01, 0, " 0: 1E-02"),
|
(0.01, 0, " 1E-02"),
|
||||||
(0, -0.1, 0, " 0: -1E-01"),
|
(-0.1, 0, "-1E-01"),
|
||||||
// i
|
// i
|
||||||
(22, 1.0, 0, "22: 1E+00"),
|
(1.0, 0, " 1E+00"),
|
||||||
// Precision
|
// Precision
|
||||||
(0, -0.123456789, 3, " 0: -1.235E-01"),
|
(-0.123456789, 3, "-1.235E-01"),
|
||||||
(0, -0.123456789, 2, " 0: -1.23E-01"),
|
(-0.123456789, 2, "-1.23E-01"),
|
||||||
(0, -0.123456789, 2, " 0: -1.23E-01"),
|
(-0.123456789, 2, "-1.23E-01"),
|
||||||
(0, -1e99, 2, " 0: -1.00E+99"),
|
(-1e99, 2, "-1.00E+99"),
|
||||||
(0, -1e100, 2, " 0: -1.00E+100"),
|
(-1e100, 2, "-1.00E+100"),
|
||||||
] {
|
] {
|
||||||
assert_eq!(fmt_scientific(i, f, p), s);
|
assert_eq!(fmt_scientific(f, p), s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fmt_separated() {
|
fn test_fmt_separated() {
|
||||||
for (i, f, c, s) in vec![
|
for (f, c, s) in vec![
|
||||||
(10, 100.0, ',', "10: 100"),
|
(100.0, ',', "100"),
|
||||||
(0, 100.0, ',', " 0: 100"),
|
(100.0, ',', "100"),
|
||||||
(0, -100.0, ',', " 0: -100"),
|
(-100.0, ',', "-100"),
|
||||||
(0, 1_000.0, ',', " 0: 1,000"),
|
(1_000.0, ',', "1,000"),
|
||||||
(0, -1_000.0, ',', " 0: -1,000"),
|
(-1_000.0, ',', "-1,000"),
|
||||||
(0, 10_000.0, ',', " 0: 10,000"),
|
(10_000.0, ',', "10,000"),
|
||||||
(0, -10_000.0, ',', " 0: -10,000"),
|
(-10_000.0, ',', "-10,000"),
|
||||||
(0, 100_000.0, ',', " 0: 100,000"),
|
(100_000.0, ',', "100,000"),
|
||||||
(0, -100_000.0, ',', " 0: -100,000"),
|
(-100_000.0, ',', "-100,000"),
|
||||||
(0, 1_000_000.0, ',', " 0: 1,000,000"),
|
(1_000_000.0, ',', "1,000,000"),
|
||||||
(0, -1_000_000.0, ',', " 0: -1,000,000"),
|
(-1_000_000.0, ',', "-1,000,000"),
|
||||||
(0, 1_000_000.123456789, ',', " 0: 1,000,000.123456789"),
|
(1_000_000.123456789, ',', "1,000,000.123456789"),
|
||||||
(0, -1_000_000.123456789, ',', " 0: -1,000,000.123456789"),
|
(-1_000_000.123456789, ',', "-1,000,000.123456789"),
|
||||||
(0, 1_000_000.123456789, ' ', " 0: 1 000 000.123456789"),
|
(1_000_000.123456789, ' ', "1 000 000.123456789"),
|
||||||
(0, 1_000_000.123456789, ' ', " 0: 1 000 000.123456789"),
|
(1_000_000.123456789, ' ', "1 000 000.123456789"),
|
||||||
] {
|
] {
|
||||||
assert_eq!(fmt_separated(i, f, c), s);
|
assert_eq!(fmt_separated(f, c), s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user