#order #operations #algebraic-expressions #calculator #expression #variables #correct

calc_lib

A library for calculating things with correct order of operations

16 stable releases

2.1.0 Feb 12, 2022
2.0.0 Jan 27, 2022
1.7.0 Jan 27, 2022
0.1.0 Jan 17, 2022

#8 in #correct

MIT license

37KB
757 lines

calc_lib

A crate for evaluating algebraic expressions from input using correct order of operations.
This was designed originally for use in terminal based calculator apps.

Features

  • Basic algebraic operations
  • Proper order of operations (functions are always evaluated first, then PEMDAS)
  • Optional defined variables
  • Integer operations and floating point operations (either/or)
  • Functions such as log, sin, cos, tan, etc.
  • Optional defined functions

Planned Features

  • equation validation (such as 2 + 2 = 4 which is valid, and 2 + 2 = 5 which is not)
  • solving for a variable (such as x + 2 = 4 will result in x = 2)

Features that may be implemented in the future

  • solving for multiple variables (such as 3x - y = 7, 2x + y = 8 will result in x = 3, y = 2)

Default functions

accessed with Functions::default();

  • log(base, value)
  • sqrt(value)
  • sin(value)
  • cos(value)
  • tan(value)

Custom Error system:

  • Exposes the Error enum which allows the user to determine what type of error occurred, and have all the relevant information about it
  • Allows for the user to handle errors in their own way if needed, but they can also just be printed out.

Examples:

Integer equations:

// evaluates an algebraic equation
use calc_lib::evaluate;

fn main() {
    // the equation to evaluate
    let eval = evaluate("1 + 2 * 3");
    // print out errors if they occur, or handle them another way
    if eval.is_err() {
        panic!("{}", eval.err().unwrap());
    }
    // the result is a f64, which can then be used as needed
    // here, I am just asserting that it is the value it should be.
    assert_eq!(eval.unwrap() as i32, 7);
}

Decimal Equations:

use calc_lib::evaluate;

fn main() {
    // define the expression
    let expression = "1.3 + 2.5 * 3.1";
    // evaluate the expression
    let eval = evaluate(expression);
    // handle errors that may occur
    if eval.is_err() {
        panic!("{}", x.unwrap_err());
    }
    assert_eq!(eval.unwrap(), 9.05);
}

Solving with variables:

use calc_lib::{evaluate_with_defined, Definitions, Functions, Error};

fn main() {
    // define x as 16
    let mut defs = Definitions::new();
    defs.register("x", 16);
  
    // create the functions list
    // this defines an empty Functions struct with no functions.
    // for functions like log, sqrt, sin, cos, tan, etc., use `Functions::default()`
    let mut funcs = Functions::new();
    // this shows the definition of the log function,
    // exactly how it is implemented in `Functions::default();`
    funcs.register("log", |args| {
        // args is of type Vec<f64>
        // this takes 2 arguments: base, number
        if args.len() != 2 {
            return Err(Error::arg_count("log", 2, args.len()));
        }
        // return the value
        Ok(args[1].log(args[0]))
    });
    // evaluate the expression and verify the results
    let eval = evaluate_with_defined("log(2, x)", Some(&defs), Some(&funcs));
    if eval.is_err() { 
      panic!("{}", eval.unwrap_err());
    }
    assert_eq!(eval.unwrap(), 4.0);
}

No runtime deps