9个版本

使用旧的Rust 2015

0.2.0 2018年9月30日
0.1.0 2017年11月11日
0.0.9 2017年2月21日
0.0.7 2016年12月7日
0.0.5 2016年7月25日

#502 in 数学

Download history 1737/week @ 2024-03-14 1831/week @ 2024-03-21 1646/week @ 2024-03-28 1091/week @ 2024-04-04 1161/week @ 2024-04-11 1227/week @ 2024-04-18 1137/week @ 2024-04-25 981/week @ 2024-05-02 1033/week @ 2024-05-09 1140/week @ 2024-05-16 1213/week @ 2024-05-23 1319/week @ 2024-05-30 1009/week @ 2024-06-06 1094/week @ 2024-06-13 1095/week @ 2024-06-20 932/week @ 2024-06-27

4,363次每月下载
用于 46 个Crates (30个直接使用)

Unlicense/MIT

78KB
1.5K SLoC

Build Status meval at docs.rs

meval

这个Rust crate提供了一个简单的数学表达式解析和评估。其主要目标是便于使用,同时提供一些灵活性。目前仅支持f64类型。一个典型的用例是在Rust中配置数值计算,比如通过配置文件或命令行参数来考虑初始数据和边界条件。

文档

安装

只需将相应的条目添加到您的Cargo.toml依赖项列表中

[dependencies]
meval = "0.2"

并将此添加到您的crate根目录中

extern crate meval;

需要Rust 1.26。

简单示例

extern crate meval;

fn main() {
    let r = meval::eval_str("1 + 2").unwrap();

    println!("1 + 2 = {}", r);
}

需要从表达式定义Rust函数?没问题,使用Expr来处理此操作及更多

extern crate meval;

fn main() {
    let expr: meval::Expr = "sin(pi * x)".parse().unwrap();
    let func = expr.bind("x").unwrap();

    let vs: Vec<_> = (0..100+1).map(|i| func(i as f64 / 100.)).collect();

    println!("sin(pi * x), 0 <= x <= 1: {:?}", vs);
}

自定义常量和函数?定义一个Context

use meval::{Expr, Context};

let y = 1.;
let expr: Expr = "phi(-2 * zeta + x)".parse().unwrap();

// create a context with function definitions and variables
let mut ctx = Context::new(); // built-ins
ctx.func("phi", |x| x + y)
   .var("zeta", -1.);
// bind function with a custom context
let func = expr.bind_with_context(ctx, "x").unwrap();
assert_eq!(func(2.), -2. * -1. + 2. + 1.);

对于2、3和N个变量的函数,分别使用Context::func2Context::func3Context::funcn。有关更多选项,请参阅Context

如果您需要一个依赖于可变参数的自定义函数,您将需要使用Cell

use std::cell::Cell;
use meval::{Expr, Context};
let y = Cell::new(0.);
let expr: Expr = "phi(x)".parse().unwrap();

let mut ctx = Context::empty(); // no built-ins
ctx.func("phi", |x| x + y.get());

let func = expr.bind_with_context(ctx, "x").unwrap();
assert_eq!(func(2.), 2.);
y.set(3.);
assert_eq!(func(2.), 5.);

支持的表达式

meval支持浮点数的基本数学运算

  • 二元运算符:+-*/%(余数)、^(幂)
  • 一元运算符:+-

它支持自定义变量和函数,如 xweightC_0f(1) 等。变量或函数名必须以 [a-zA-Z_] 开头,并且只能包含 [a-zA-Z0-9_]。还支持具有可变参数数量的自定义函数。

内置函数(由 Context::new() 提供,在没有提供上下文的情况下)目前支持

  • 使用与 Rust std 库 中同名函数实现的函数

    • sqrtabs
    • expln
    • sincostanasinacosatanatan2
    • sinhcoshtanhasinhacoshatanh
    • floorceilround
    • 符号函数
  • 其他函数

    • max(x, ...)min(x, ...):1 个或多个数字的最大值和最小值
  • 常量

    • π
    • e

反序列化

Expr 支持使用 serde 库进行反序列化,以简化灵活配置的设置,如果启用了功能 serde(默认禁用)。

#[macro_use]
extern crate serde_derive;
extern crate toml;
extern crate meval;
use meval::{Expr, Context};

#[derive(Deserialize)]
struct Ode {
    #[serde(deserialize_with = "meval::de::as_f64")]
    x0: f64,
    #[serde(deserialize_with = "meval::de::as_f64")]
    t0: f64,
    f: Expr,
}

fn main() {
    let config = r#"
        x0 = "cos(1.)"
        t0 = 2
        f = "sin(x)"
    "#;
    let ode: Ode = toml::from_str(config).unwrap();

    assert_eq!(ode.x0, 1f64.cos());
    assert_eq!(ode.t0, 2f64);
    assert_eq!(ode.f.bind("x").unwrap()(2.), 2f64.sin());
}

这是我为了学习 Rust 而创建的一个玩具项目,希望在编写命令行脚本时能有所帮助。没有计划将其做成“数学表达式 -> 数字”的“转换器”以外的任何东西。对于更高级的脚本,请参阅

  • dyon -- 一个 Rust 动态类型脚本语言
  • gluon -- 一个用于应用嵌入的静态、类型推断编程语言
  • rodolf0/tox -- 另一个后缀表达式解析器

许可证

本项目由 Unlicense 和 MIT 许可证共同许可。

您可以在任一许可证的条款下使用此代码。

依赖项

~1MB
~17K SLoC