#calculator #scientific #expression #parser

bin+lib rsc

一个用于解决字符串中科学和代数数学方程的快速计算器

12 个版本 (6 个稳定版)

3.0.0 2024年3月31日
2.0.0 2019年6月17日
1.2.1 2019年6月16日
1.2.0 2019年1月1日
0.1.5 2018年8月28日

#43 in 数学

Download history 238/week @ 2024-04-23 130/week @ 2024-04-30 206/week @ 2024-05-07 189/week @ 2024-05-14 254/week @ 2024-05-21 152/week @ 2024-05-28 283/week @ 2024-06-04 158/week @ 2024-06-11 138/week @ 2024-06-18 119/week @ 2024-06-25 126/week @ 2024-07-02 124/week @ 2024-07-09 179/week @ 2024-07-16 158/week @ 2024-07-23 172/week @ 2024-07-30 157/week @ 2024-08-06

673 每月下载量
用于 typenum-consts

MIT 许可证

37KB
861

RSC,Rust 代码计算器

更新:crate 更新到 3.0,请参阅 变更日志

RSC 是一个手写的科学计算器,用于解释字符串中的方程。 RSC 设计得很好,可以很好地完成一项工作,使任何人都可以通过添加更多功能来扩展它。

RSC 旨在超越 Wirth 定律。 因此,RSC 将不会接收很多新增功能。 它仍会接收与效率相关的更新。

use rsc::{tokenize, parse, Interpreter};

// Maybe you write a wrapper function
fn evaluate(input: &str, interpreter: &mut Interpreter<f64>) -> Result<f64, ()> {
    // You have to call each function in the pipeline, but this gives you the most
    // control over error handling and performance.
    match tokenize(input) { // Step 1: splits input into symbols, words, and numbers
        Ok(tokens) => match parse(&tokens) { // Step 2: builds an Expr using tokens
            Ok(expr) => match interpreter.eval(&expr) { // Step 3: interprets the Expr
                Ok(result) => println!("{}", result),
                Err(interpret_error) => eprintln!("{:?}", interpret_error),
            },
            Err(parse_error) => eprintln!("{:?}", parse_error),
        },
        Err(tokenize_error) => eprintln!("{:?}", tokenize_error),
    }
}

fn main() {
    // Constructs an f64 interpreter with included variables
    let mut interpreter = Interpreter::default();
    
    evaluate("5^2", &mut interpreter); // prints "25"
    evaluate("x = 3", &mut interpreter); // prints "3"
    evaluate("x(3) + 1", &mut interpreter); // prints "10"
}

变量存储在 解释器

use rsc::{tokenize, parse, Interpreter, Variant, InterpretError};

// assume you still had your evaluate function above

fn main() {
    // Create a completely empty interpreter for f64 calculations
    let mut i = Interpreter::<f64>::new();
    
    // Create some variables
    i.set_var(String::from("pi"), Variant::Num(std::f64::consts::PI));
    i.set_var(String::from("double"), Variant::Function(|name, args| {
        if args.len() < 1 {
            Err(InterpretError::TooFewArgs(name, 1))
        } else if args.len() > 1 {
            Err(InterpretError::TooManyArgs(name, 1))
        } else {
            Ok(args[0] * 2) // get the only argument and double it
        }
    }));
    
    evaluate("double(pi)", &mut i); // prints "6.283185307179586"
}

由于可能存在冗余检查函数是否接收了正确的参数数量(如果您愿意这么做的话),我创建了一个名为 ensure_arg_count 的辅助函数。上面的函数重新定义了

use rsc::ensure_arg_count;

i.set_var(String::from("double"), Variant::Function(|name, args| {
    // return Err if args are not within the min and max count
    ensure_arg_count(1, 1, args.len(), name)?;
    Ok(args[0] * 2)
}));

可执行文件

您可能需要首先将 RSC 构建为可执行文件

cargo build --release --features=executable

需要 executable 功能来告诉 crate 仅将某些依赖项用于可执行版本,用于终端中的颜色和参数解析。

用法

RSC interactive expression interpreter.
Try "help" for commands and examples.
>sqrt(15+3)
:4.242640687119285
>:square root
>sqrt(15, 3)
Function "sqrt" received more than the maximum 1 argument.
> |-5|
:5
>abs(-5)
:5
>sqrt(4)(2)
        ^ UnexpectedToken(Token { value: Symbol(LP), span: 7..8 })
>(sqrt(4))(2)
:4
>x = 1.24
:1.24
>x(4)
:4.96
>vars
factorial(..)
sqrt(..)
abs(..)
x = 1.24
e = 2.718281828459045
pi = 3.141592653589793
tau = 6.283185307179586

可以直接将表达式传递给 rsc

$ rsc "12/sqrt(128)"
1.0606601717798212

您可以传递各种标志。尝试

rsc -tev
$ rsc -h
rsc 3.0.0
A scientific calculator for the terminal.

USAGE:
    rsc [FLAGS] [expr]

FLAGS:
    -e, --expr        Prints the expression tree
    -h, --help        Prints help information
        --no-color    Prevents colored text
    -t, --tokens      Prints the tokens
    -v, --vars        Prints variable map
    -V, --version     Prints version information

ARGS:
    <expr>

关于性能的说明

  • 词法分析器是迭代的,很容易进行优化。
  • 解析器是一个 LL(2) 递归下降解析器,这是我想到的最简单、最蛮力的解析解决方案。它很容易理解和维护,但不是最有效的。解析器目前是三个阶段中最慢的。
  • 解释器::评估 函数使用递归以保持简单。移除递归可以防止不必要的帧指针的推送和弹出,并启用更好的缓存,从而提供更好的性能。
  • 欢迎提交性能改进的 PR,这可能是很容易的!

稳定性

RSC 不会对其语法进行任何重大更改。它将保持一致性很长时间。创建不同版本的 RSC 是分叉者的责任。它也将永远保持相同的开源权限。

许可证

RSC 是 MIT 许可证。RSC 将始终免费修改和使用,无需署名。

依赖项

~0–10MB
~49K SLoC