diff --git a/src/main.rs b/src/main.rs index 107dbf5..247ba53 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,8 +12,22 @@ pub fn parse_and_calc(s: &str) -> Float { nodes::Nodes::from_str(s).unwrap().evaluate() } +pub fn get_significant_digits(n: &Float) -> usize { + let raw_string = format!("{n}"); + + let mut significant_digits = raw_string.len() - 1; + for (i, _) in raw_string.char_indices() { + if !raw_string[i..raw_string.len()].contains(|c| matches!(c, '1'..'9')) { + significant_digits = i; + break; + } + } + + significant_digits +} + fn main() { - let input = match env::args().nth(1) { + let input = match env::args().skip(1).reduce(|x, a| a + &x) { Some(s) => s, None => { let mut buf = String::new(); @@ -22,5 +36,7 @@ fn main() { } }; - println!("{:.3}", parse_and_calc(&input)); + let result = parse_and_calc(&input); + + println!("{result:.0$}", get_significant_digits(&result).clamp(0, 6)); } diff --git a/src/nodes/evaluate.rs b/src/nodes/evaluate.rs index eae3d8e..c9984bd 100644 --- a/src/nodes/evaluate.rs +++ b/src/nodes/evaluate.rs @@ -40,6 +40,8 @@ fn collapse_toplevel(nodes: &mut Vec, mut end: usize) { { match &mut nodes[start..end][index + 1] { Node::Number(n) => match variant { + Function::Sqrt => n.sqrt_mut(), + Function::Sine => n.sin_mut(), Function::ArcSine => n.asin_mut(), Function::Cosine => n.cos_mut(), diff --git a/src/nodes/from_str.rs b/src/nodes/from_str.rs index 4f0f20d..a28b15a 100644 --- a/src/nodes/from_str.rs +++ b/src/nodes/from_str.rs @@ -1,3 +1,4 @@ +use core::f64; use std::str::FromStr; use rug::{Float, float::ParseFloatError, ops::CompleteRound}; @@ -9,6 +10,7 @@ impl Node { Ok(match s { "c" => Self::Number(Float::with_val(PREC, 299_792_458)), "A" => Self::Number(Float::with_val(PREC, 6.02214076e23)), + "pi" => Self::Number(Float::with_val(PREC, f64::consts::PI)), _ => Self::Function(s.parse()?), }) } @@ -19,8 +21,8 @@ impl TryFrom for Operator { match value { '+' => Ok(Self::Plus), '-' => Ok(Self::Minus), - '*' => Ok(Self::Mult), - '/' => Ok(Self::Div), + '*' | '×' => Ok(Self::Mult), + '/' | '÷' => Ok(Self::Div), '^' => Ok(Self::Exp), _ => Err(value), } @@ -30,6 +32,8 @@ impl FromStr for Function { type Err = String; fn from_str(s: &str) -> Result { match s { + "sqrt" => Ok(Self::Sqrt), + "sin" => Ok(Self::Sine), "asin" => Ok(Self::ArcSine), "cos" => Ok(Self::Cosine), diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index a7326bf..f46ad3b 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -40,6 +40,8 @@ enum Operator { #[derive(Debug, Copy, Clone, PartialEq)] enum Function { + Sqrt, + Sine, ArcSine, Cosine, diff --git a/src/nodes/tests.rs b/src/nodes/tests.rs index 4c3caa6..ae50576 100644 --- a/src/nodes/tests.rs +++ b/src/nodes/tests.rs @@ -1,9 +1,18 @@ +use core::f64; use std::str::FromStr; use rug::Float; use crate::nodes::{Function, Node, Nodes, Operator, PREC}; +#[test] +fn implicit_mult() { + assert_eq!( + Nodes::from_str("10 sin(10)").unwrap().evaluate().to_f64(), + -5.440211108893698 + ); +} + #[test] fn constants() { assert_eq!( @@ -14,6 +23,10 @@ fn constants() { Nodes::from_str("A").unwrap().evaluate().to_f64(), 6.02214076e23 ); + assert_eq!( + Nodes::from_str("pi").unwrap().evaluate().to_f64(), + f64::consts::PI + ); } #[test]