Flutter表达式计算插件tiny_expr的使用
Flutter表达式计算插件tiny_expr的使用
简介
TinyExpr 是一个轻量级的 Dart 表达式求值库,旨在从字符串中评估数学表达式。这使得它成为需要动态计算的应用程序的理想选择。
该项目灵感来自于C语言编写的 TinyExpr 库,原库可以在这里找到。我们对原作者的杰出工作表示感谢。
功能特性
- 从字符串中评估数学表达式。
- 支持基本算术运算:加法、减法、乘法和除法。
- 支持括号以定义操作优先级。
- 支持指数运算。
- 支持一元取反。
- 支持常数(如
pi
,e
)。 - 支持三角函数(如
sin
,cos
,tan
,cosec
,sec
,cot
)。 - 支持双曲函数(如
sinh
,cosh
,tanh
)。 - 支持对数函数(如
log
,ln
)。 - 支持平方根和绝对值。
- 支持指数函数。
- 支持舍入函数(如
ceil
,floor
)。 - 支持阶乘、组合(nCr)和排列(nPr)。
- 轻量且易于集成。
- 支持在
String
上扩展方法以直接使用.evaluate()
方法。
入门指南
要开始使用 TinyExpr,请在 pubspec.yaml
文件中添加它作为依赖项:
dependencies:
tiny_expr: ^0.3.1
然后运行 flutter pub get
来安装该包。
使用方法
简单实现
以下是如何使用 TinyExpr 评估表达式的简单示例:
import 'package:tiny_expr/tiny_expr.dart';
void main() {
final expression = '3 + 5 * (2 - 4)';
final result = TinyExpr(expression).evaluate();
print('Result: $result'); // Output: Result: -7
}
使用变量
以下是如何使用 TinyExpr 带有变量的示例:
import 'package:tiny_expr/tiny_expr.dart';
void main() {
final expression = 'x + y * z';
final te = TinyExpr(expression);
te.addVariables({'x': 3.0, 'y': 2.0, 'z': 5.0});
final result = te.evaluate();
print('Result: $result'); // Output: Result: 13.0
// 更新变量值
te.updateVariables({'x': 10.0});
final updatedResult = te.evaluate();
print('Updated Result: $updatedResult'); // Output: Updated Result: 20.0
}
使用扩展方法
TinyExpr 现在支持在 String
上扩展方法以直接评估表达式:
import 'package:tiny_expr/tiny_expr.dart';
void main() {
final expression = '3 + 5 * (2 - 4)';
final result = expression.evaluate();
final expressionWithVariables = 'x + y';
final resultWithVariables =
expressionWithVariables.evaluate(variables: {'x': 2, 'y': 15});
print('Result: $result'); // Output: Result: -7
print('Result: $resultWithVariables'); // Output: Result: 17
}
更多示例可以在 /example
文件夹中查看。
可用操作
操作类型 | 运算符/函数 | 示例 |
---|---|---|
基本算术 | + , - , * , / , % |
2 + 3 , 10 - 4 , 6 * 7 , 20 / 5 , 8 % 3 |
指数运算 | ^ |
2^3 |
括号 | () |
(2 + 3) * 4 |
一元取反 | - |
-5 , -(2 + 3) |
常数 | pi , e |
pi , e |
三角函数 | sin , cos , tan , cosec , sec , cot , atan2 |
sin(pi / 2) , cos(pi) , tan(pi / 4) , cosec(pi / 2) , sec(0) , cot(pi / 4) , atan2(1, 1) |
双曲函数 | sinh , cosh , tanh |
sinh(1) , cosh(1) , tanh(1) |
对数函数 | log , ln |
log(100) , ln(e) |
平方根 | sqrt |
sqrt(16) |
绝对值 | abs |
abs(-5) |
指数函数 | exp |
exp(1) |
舍入函数 | ceil , floor |
ceil(2.1) , floor(2.9) |
阶乘 | fac , ! |
fac(5) , 5! |
组合 | ncr |
ncr(5, 3) |
排列 | npr |
npr(5, 2) |
测试覆盖范围
TinyExpr 包含全面的测试,以确保表达式评估的正确性。测试涵盖以下内容:
- 基本算术
- 指数运算
- 括号和优先级
- 一元取反
- 常数
- 三角函数
- 双曲函数
- 对数函数
- 平方根和绝对值
- 指数函数
- 舍入函数
- 阶乘
- 组合和排列
- 变量处理
- 嵌套表达式
- 复杂表达式
- 错误处理
文档覆盖范围
TinyExpr 包文档齐全,包含详细的功能说明、使用示例和 API 参考。文档涵盖以下部分:
- 概述
- 功能和限制
- 入门指南
- 使用示例
- 可用操作
- API 参考
未来计划
未来的计划包括:
- 添加更多高级数学函数(如双曲三角函数、特殊函数)
- 提高复杂表达式的性能
- 添加用户自定义函数的支持
- 增强错误处理和报告
- 提供更多使用示例和文档
- 添加更多数学常数的支持
- 添加更多扩展方法
更多信息
更多信息请访问 TinyExpr GitHub 仓库。
要为这个包做贡献,请提交 pull request 或者在 GitHub 上提交问题。我们欢迎贡献,并将尽快响应问题。
如果您遇到任何问题或有任何疑问,请随时在 GitHub 上提交问题,我们将尽力提供及时的帮助。
示例代码
以下是完整的示例代码,用于测试 TinyExpr 的各种功能:
import 'dart:math';
import 'package:tiny_expr/tiny_expr.dart';
void main() {
// 测试 TinyExpr 评估器,给定表达式和预期结果
void testExpression(String expression, double expected,
{bool approx = false}) {
try {
final te = TinyExpr(expression);
final result = te.evaluate();
if (approx) {
// 对于近似比较(例如浮点结果)
if ((result - expected).abs() < 1e-6) {
print("✅ Passed: $expression = $result (expected: $expected)");
} else {
print("❌ Failed: $expression = $result (expected: $expected)");
}
} else {
// 对于精确比较
if (result == expected) {
print("✅ Passed: $expression = $result");
} else {
print("❌ Failed: $expression = $result (expected: $expected)");
}
}
} catch (e) {
print("❌ Failed: $expression threw an error: $e");
}
}
// 运行所有测试
print("Starting tests...\n");
// 基本算术
testExpression("2 + 3", 5.0);
testExpression("10 - 4", 6.0);
testExpression("6 * 7", 42.0);
testExpression("20 / 5", 4.0);
testExpression("8 % 3", 2.0);
// 指数运算
testExpression("2^3", 8.0);
testExpression("5^0", 1.0);
// 括号和操作优先级
testExpression("(2 + 3) * 4", 20.0);
testExpression("2 + 3 * 4", 14.0);
testExpression("(2 + 3)^2", 25.0);
// 一元取反
testExpression("-5", -5.0);
testExpression("-(2 + 3)", -5.0);
// 常数
testExpression("pi", pi, approx: true);
testExpression("e", e, approx: true);
// 三角函数
testExpression("sin(pi / 2)", 1.0, approx: true);
testExpression("cos(pi)", -1.0, approx: true);
testExpression("tan(pi / 4)", 1.0, approx: true);
testExpression("atan2(1, 1)", pi / 4, approx: true);
testExpression("cosec(pi / 2)", 1.0, approx: true);
testExpression("sec(0)", 1.0, approx: true);
testExpression("cot(pi / 4)", 1.0, approx: true);
// 双曲函数
testExpression("sinh(1)", sinh(1.0), approx: true);
testExpression("cosh(1)", cosh(1.0), approx: true);
testExpression("tanh(1)", tanh(1.0), approx: true);
// 对数函数
testExpression("log(100)", 2.0);
testExpression("ln(e)", 1.0, approx: true);
// 平方根和绝对值
testExpression("sqrt(16)", 4.0);
testExpression("abs(-5)", 5.0);
// 指数函数
testExpression("exp(1)", e, approx: true);
// 舍入函数
testExpression("ceil(2.1)", 3.0);
testExpression("floor(2.9)", 2.0);
// 阶乘
testExpression("fac(5)", 120.0);
testExpression("fac(0)", 1.0);
testExpression("fac(1)", 1.0);
testExpression("5!", 120.0); // 阶乘运算符示例
testExpression("0!", 1.0); // 阶乘运算符示例
testExpression("1!", 1.0); // 阶乘运算符示例
// 组合(nCr)和排列(nPr)
testExpression("ncr(5, 3)", 10.0);
testExpression("npr(5, 2)", 20.0);
// 变量
try {
final teWithVars = TinyExpr("x + y * z");
teWithVars.addVariables({"x": 3.0, "y": 2.0, "z": 5.0});
final result = teWithVars.evaluate();
if (result == 13.0) {
print("✅ Passed: x + y * z with variables = $result");
} else {
print("❌ Failed: x + y * z with variables = $result (expected: 13.0)");
}
// 更新变量值
teWithVars.updateVariables({"x": 10.0});
final updatedResult = teWithVars.evaluate();
if (updatedResult == 20.0) {
print("✅ Passed: Updated x = $updatedResult");
} else {
print("❌ Failed: Updated x = $updatedResult (expected: 20.0)");
}
} catch (e) {
print("❌ Failed: Variable tests threw an error: $e");
}
// 嵌套表达式
testExpression("fac(3) + ncr(5, 2) * sqrt(16)", 6 + 10 * 4);
// 复杂表达式
testExpression("2 + 3 * (4 - 1)^2 / 2", 15.5);
testExpression("5! + 3^2 - sqrt(16) * log(100)", 120.0 + 9 - 4 * 2);
testExpression("sin(pi / 2) + cos(0) * tan(pi / 4)", 1.0 + 1.0 * 1.0,
approx: true);
testExpression("exp(1) + ln(e) - fac(3)", e + 1.0 - 6.0, approx: true);
testExpression("ceil(2.1) + floor(2.9) * abs(-5)", 3.0 + 2.0 * 5.0);
// 错误处理
try {
TinyExpr("unknown").evaluate();
print("❌ Failed: Unknown variable/function should throw error");
} catch (e) {
print("✅ Passed: Unknown variable/function error handled: $e");
}
try {
TinyExpr("5 +").evaluate();
print("❌ Failed: Incomplete expression should throw error");
} catch (e) {
print("✅ Passed: Incomplete expression error handled: $e");
}
try {
TinyExpr("log(-1)").evaluate();
print("❌ Failed: log(-1) should throw error or return NaN");
} catch (e) {
print("✅ Passed: log(-1) error handled: $e");
}
print("\nAll tests completed!");
}
希望这些内容能帮助您更好地理解和使用 TinyExpr 插件!
更多关于Flutter表达式计算插件tiny_expr的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter表达式计算插件tiny_expr的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用tiny_expr
插件来进行表达式计算的示例代码。tiny_expr
是一个轻量级的数学表达式求值库,虽然它本身不是一个Flutter插件,但可以通过Dart的FFI(外部函数接口)或者通过平台通道与原生代码交互来使用。不过,为了简化示例,这里假设你已经有一个现成的Dart封装或者通过其他方式可以在Dart中调用tiny_expr
的功能。
步骤 1: 添加依赖
首先,确保你的pubspec.yaml
文件中添加了必要的依赖。由于tiny_expr
不是直接可用的Flutter插件,你可能需要手动集成或者使用已有的Dart封装(如果有的话)。这里假设你已经有了某种方式可以在Dart中调用tiny_expr
。
步骤 2: 创建一个Flutter项目并集成表达式计算逻辑
假设你已经创建了一个Flutter项目,接下来我们将集成表达式计算逻辑。
main.dart
import 'package:flutter/material.dart';
import 'expression_evaluator.dart'; // 假设这是封装了tiny_expr功能的Dart文件
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Tiny Expr Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final TextEditingController _controller = TextEditingController();
String _result = '';
void _evaluateExpression() {
String expression = _controller.text;
try {
double result = evaluateExpression(expression);
setState(() {
_result = 'Result: $result';
});
} catch (e) {
setState(() {
_result = 'Error: ${e.toString()}';
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Tiny Expr Demo'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
controller: _controller,
decoration: InputDecoration(
labelText: 'Enter Expression',
),
keyboardType: TextInputType.multiline,
maxLines: 5,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _evaluateExpression,
child: Text('Evaluate'),
),
SizedBox(height: 20),
Text(_result),
],
),
),
);
}
}
expression_evaluator.dart
这个文件封装了调用tiny_expr
的逻辑(这里假设你已经有了某种方式调用它,实际实现可能涉及更多的原生代码集成)。
// 这是一个假设的封装,实际实现可能需要更多的原生代码集成
double evaluateExpression(String expression) {
// 这里应该是调用tiny_expr的逻辑
// 由于tiny_expr不是直接可用的Dart库,这里只是模拟一个简单的表达式求值
// 实际的实现可能涉及调用C/C++代码或者通过FFI/平台通道
// 假设表达式只包含基础的数学运算
// 注意:以下代码仅为示例,不支持复杂的表达式解析和错误处理
try {
return double.parse(expression.replaceAll(RegExp(r'\s+'), '').replaceAll('x', '10').calculate());
} catch (e) {
throw Exception('Invalid expression');
}
}
// 注意:上面的calculate()方法并不存在,这里只是为了演示
// 你需要实现一个真正的表达式解析和计算逻辑,可能通过tiny_expr或其他库
注意
-
实际集成:上面的
expression_evaluator.dart
文件只是一个占位符,实际中你需要实现与tiny_expr
的交互逻辑。这可能涉及到使用Dart的FFI调用C/C++代码,或者通过平台通道与原生Android/iOS代码交互。 -
错误处理:在实际应用中,你需要添加更详细的错误处理逻辑,以处理各种可能的表达式错误。
-
性能:对于复杂的表达式,确保你的实现是高效的,特别是在移动设备上运行时。
-
安全性:确保你的表达式解析器是安全的,防止注入攻击等安全问题。
由于tiny_expr
本身不是为Dart/Flutter设计的,因此集成它可能需要一些额外的工作。如果你不熟悉FFI或平台通道的使用,可能需要进一步学习这些技术。