#math-expressions #expression-parser #parser #expression #evaluator #arithmetic-operations

lieval

一个轻量级的 Rust 包,用于从字符串解析和评估数学表达式

8 个版本

0.2.4 2024年6月4日
0.2.3 2024年6月3日
0.2.2 2024年5月31日
0.1.2 2024年5月1日
0.1.1 2024年4月29日

#37 in 解析工具

Download history 366/week @ 2024-04-26 163/week @ 2024-05-03 155/week @ 2024-05-10 26/week @ 2024-05-17 4/week @ 2024-05-24 435/week @ 2024-05-31 57/week @ 2024-06-07 14/week @ 2024-06-14 3/week @ 2024-06-21

561 每月下载量

MIT 协议

53KB
1K SLoC

lieval

lieval 是一个轻量级的 Rust 包,用于从字符串解析和评估数学表达式。

功能

  • 解析和评估简单的数学表达式。
    • 基本算术运算:+-*/%
    • 表达式分组使用括号
    • 常用数学函数:sincosatancoshpowsqrthypotexplndiv_euclidfloor 等...
    • 数学常数,如 PITAUE
  • 支持变量、运算符和函数。
  • 最小化依赖。
  • 提供简单易用的 API。

用法

lieval 包添加到您的 Cargo.toml 文件中

[dependencies]
lieval = "<version>"

然后,在您的 Rust 代码中

use lieval::*;

assert_eq!(eval_from_str("1.0 + 2 * (3 - 1)"), Ok(vec![5.0]));
assert_eq!(
    eval_from_str("1.0 - sin(3.14 / 2) * powf(1.5, 2.5)"),
    Ok(vec![1.0 - (3.14f64 / 2.0).sin() * 1.5f64.powf(2.5)])
);

let mut expr = Expr::new("sqrt(4)").unwrap();
assert_eq!(expr.eval(), Ok(2.0));

// using macro `ex!`
assert_eq!(ex!("sqrt(4)").eval(), Ok(2.0));

您可以使用 Context 将数值赋给变量并评估它们。

# use lieval::*;
#
let mut context = Context::new();

assert_eq!(
    eval_from_str_with_context("1 / x", context.set_value("x", 2.0)),
    Ok(vec![0.5])
);

assert_eq!(ex!("sqrt(2+x)").set_var("x", 2.0).eval(), Ok(2.0));
assert_eq!(ex!("sqrt(2+x+y)").set_var("x", 2.0).set_var("y", 5.0).eval(), Ok(3.0));

您可以使用自定义函数。

# use lieval::*;
# 
let mut context = Context::new();

assert_eq!(
    eval_from_str_with_context("1 + func(2,3)", context.set_func("func", 2, |x| x[0] + x[1])),
    Ok(vec![6.0])
);
assert_eq!(
    ex!("1 + func(x)").set_func("func", 1, |x| x[0] * 2.0).set_var("x", 1.0).eval(),
    Ok(3.0)
);

您可以使用逗号或分号分隔多个表达式进行评估。

# use lieval::*;
# 
assert_eq!(
    eval_from_str("1 + 2, sin(3 + 0.14); 7 % 3"), 
    Ok(vec![3.0, (3.14f64).sin(), 7.0 % 3.0])
);

let mut expr = ex!("sqrt(1+x); 1+3, hypot(x,4)");
assert_eq!(expr.set_var("x", 3.0).evals(), Ok(vec![2.0, 4.0, 5.0]));
assert_eq!(expr.eval(), Ok(2.0));
assert_eq!(expr.eval_index(2), Ok(5.0));

您可以使用 partial_eval 进行预计算以提高效率。

# use lieval::*;
# 
let mut expr = ex!("a1 + a2 * sin(x)");
expr.set_var("a1", 1.0)
    .set_var("a2", 0.5)
    .partial_eval()
    .unwrap();
let mut x = 1.0;
for _ in 0..10 {
    x = expr.set_var("x", x).eval().unwrap();
    assert_eq!(expr.set_var("x", x).eval(), Ok(1.0 + 0.5 * x.sin()));
}

您可以在表达式对象之间执行算术运算。

# use lieval::*;
# 
let expr1 = Expr::new("1+x").unwrap();
assert_eq!((expr1 + ex!("2*x")).set_var("x", 2.0).eval(), Ok(7.0));
assert_eq!((ex!("1+x, 2+x, 3+x") + ex!("2*x, 3*x, 4*x")).set_var("x", 2.0).evals(), Ok(vec![7.0, 10.0, 13.0]));

// broadcasting
let expr1 = Expr::new("1+x").unwrap();
let expr2 = Expr::new("2*x, 3*x, 4*x").unwrap();
assert_eq!((ex!("1+x") * ex!("2*x, 3*x, 4*x")).set_var("x", 2.0).evals(), Ok(vec![12.0, 18.0, 24.0]));
assert_eq!((ex!("1+x") * 2.0 * ex!("x") + ex!("2*x, 3*x, 4*x") + 1.0).set_var("x", 2.0).evals(), Ok(vec![17.0, 19.0, 21.0]));

// If variables conflict, the variable in the left expression takes precedence,
// so use partial_eval beforehand.
let mut expr1 = Expr::new("2*x").unwrap();
expr1.set_var("x", 3.0).partial_eval().unwrap();
assert_eq!((-ex!("1+x") * expr1).set_var("x", 2.0).eval(), Ok(-18.0));

API 文档

详细的 API 文档可以在 此处 找到。

许可证

本项目采用 MIT 许可证。

依赖