rpn(1): code cleanup
This commit is contained in:
parent
90ca10990f
commit
34b9519e03
47
src/rpn.rs
47
src/rpn.rs
|
@ -69,9 +69,7 @@ enum CalcType {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct EvaluationError {
|
struct EvaluationError { pub message: String }
|
||||||
pub message: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for EvaluationError {
|
impl fmt::Display for EvaluationError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
@ -91,9 +89,7 @@ fn str_to_calc_type(string: &str) -> Option<CalcType> {
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if result.is_some() {
|
if result.is_some() { return result; }
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
match string {
|
match string {
|
||||||
"+" => Some(Add),
|
"+" => Some(Add),
|
||||||
|
@ -132,22 +128,26 @@ fn eval(
|
||||||
};
|
};
|
||||||
|
|
||||||
match x {
|
match x {
|
||||||
Add | Divide | Multiply | Power | Subtract | Modulo => {
|
|
||||||
ops.push_back(x)
|
|
||||||
},
|
|
||||||
Val(x_) => stack.push_back(x_),
|
Val(x_) => stack.push_back(x_),
|
||||||
|
_ => ops.push_back(x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for op in &ops {
|
for op in &ops {
|
||||||
match op {
|
match op {
|
||||||
Add | Subtract | Multiply | Divide | Power | Modulo => {
|
Val(_) => {
|
||||||
|
return Err(EvaluationError {
|
||||||
|
message: "Unexpected value in the operator stack."
|
||||||
|
.to_string()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
let x = &stack.pop_back().ok_or(EvaluationError {
|
let x = &stack.pop_back().ok_or(EvaluationError {
|
||||||
message: "Stack is empty.".to_string(),
|
message: "Stack is empty.".to_string(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let y = &stack.pop_back().ok_or(EvaluationError {
|
let y = &stack.pop_back().ok_or(EvaluationError {
|
||||||
message: "Stack is empty.".to_string(),
|
message: "Stack is empty.".to_string(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
|
@ -160,20 +160,13 @@ fn eval(
|
||||||
_ => &{},
|
_ => &{},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
Val(_) => {
|
|
||||||
return Err(
|
|
||||||
EvaluationError {
|
|
||||||
message: "Unexpected value in the operator stack."
|
|
||||||
.to_string()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(stack)
|
Ok(stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Round a float to the given precision level
|
||||||
fn round_precise(value: &f64, precision: usize) -> f64 {
|
fn round_precise(value: &f64, precision: usize) -> f64 {
|
||||||
let multiplier = 10_f64.powi(precision as i32);
|
let multiplier = 10_f64.powi(precision as i32);
|
||||||
(value * multiplier).round() / multiplier
|
(value * multiplier).round() / multiplier
|
||||||
|
@ -183,6 +176,8 @@ fn main() -> ExitCode {
|
||||||
let argv = args().collect::<Vec<String>>();
|
let argv = args().collect::<Vec<String>>();
|
||||||
let mut stack = VecDeque::new();
|
let mut stack = VecDeque::new();
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
// Set floating-point precision for correcting rounding errors based on
|
||||||
|
// machine epsilon
|
||||||
let precision = (-f64::EPSILON.log10() * PRECISION_MOD).ceil() as usize;
|
let precision = (-f64::EPSILON.log10() * PRECISION_MOD).ceil() as usize;
|
||||||
|
|
||||||
if argv.get(1).is_none() {
|
if argv.get(1).is_none() {
|
||||||
|
@ -196,8 +191,7 @@ fn main() -> ExitCode {
|
||||||
None => break,
|
None => break,
|
||||||
};
|
};
|
||||||
|
|
||||||
let precise = round_precise(val, precision);
|
println!("{}", round_precise(val, precision).to_string());
|
||||||
println!("{}", precise.to_string());
|
|
||||||
buf.clear();
|
buf.clear();
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -215,7 +209,16 @@ fn main() -> ExitCode {
|
||||||
.join(" ");
|
.join(" ");
|
||||||
|
|
||||||
match eval(&input, stack) {
|
match eval(&input, stack) {
|
||||||
Ok(val) => println!("{}", val.iter().last().unwrap().to_string()),
|
Ok(s) => {
|
||||||
|
stack = s.clone();
|
||||||
|
|
||||||
|
let val = match stack.iter().last() {
|
||||||
|
Some(v) => v,
|
||||||
|
None => return ExitCode::from(0),
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{}", round_precise(val, precision).to_string())
|
||||||
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("{}: {}", argv[0], err.message);
|
eprintln!("{}: {}", argv[0], err.message);
|
||||||
return ExitCode::from(EX_DATAERR as u8);
|
return ExitCode::from(EX_DATAERR as u8);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user