♻️ Replace the math expressions with own calculator

This commit is contained in:
2025-09-14 13:19:56 +08:00
parent 722ef9ca21
commit 2a56a83898
4 changed files with 90 additions and 13 deletions

View File

@@ -7,6 +7,9 @@ abstract class Expr {
/// 新增:对表达式进行“求值/数值化”——尽可能把可算的部分算出来 /// 新增:对表达式进行“求值/数值化”——尽可能把可算的部分算出来
Expr evaluate(); Expr evaluate();
/// Substitute variable with value
Expr substitute(String varName, Expr value);
@override @override
String toString(); String toString();
@@ -27,6 +30,9 @@ class IntExpr extends Expr {
@override @override
Expr evaluate() => this; Expr evaluate() => this;
@override
Expr substitute(String varName, Expr value) => this;
@override @override
String toString() => value.toString(); String toString() => value.toString();
} }
@@ -42,10 +48,31 @@ class DoubleExpr extends Expr {
@override @override
Expr evaluate() => this; Expr evaluate() => this;
@override
Expr substitute(String varName, Expr value) => this;
@override @override
String toString() => value.toString(); String toString() => value.toString();
} }
// === VarExpr ===
class VarExpr extends Expr {
final String name;
VarExpr(this.name);
@override
Expr simplify() => this;
@override
Expr evaluate() => this;
@override
Expr substitute(String varName, Expr value) => name == varName ? value : this;
@override
String toString() => name;
}
// === FractionExpr.evaluate === // === FractionExpr.evaluate ===
class FractionExpr extends Expr { class FractionExpr extends Expr {
final int numerator; final int numerator;
@@ -74,6 +101,9 @@ class FractionExpr extends Expr {
@override @override
Expr evaluate() => simplify(); Expr evaluate() => simplify();
@override
Expr substitute(String varName, Expr value) => this;
@override @override
String toString() => "$numerator/$denominator"; String toString() => "$numerator/$denominator";
} }
@@ -150,6 +180,12 @@ class AddExpr extends Expr {
return AddExpr(l, r); return AddExpr(l, r);
} }
@override
Expr substitute(String varName, Expr value) => AddExpr(
left.substitute(varName, value),
right.substitute(varName, value),
);
@override @override
String toString() => "($left + $right)"; String toString() => "($left + $right)";
} }
@@ -213,6 +249,12 @@ class SubExpr extends Expr {
return SubExpr(l, r); return SubExpr(l, r);
} }
@override
Expr substitute(String varName, Expr value) => SubExpr(
left.substitute(varName, value),
right.substitute(varName, value),
);
@override @override
String toString() => "($left - $right)"; String toString() => "($left - $right)";
} }
@@ -296,6 +338,12 @@ class MulExpr extends Expr {
return MulExpr(l, r); return MulExpr(l, r);
} }
@override
Expr substitute(String varName, Expr value) => MulExpr(
left.substitute(varName, value),
right.substitute(varName, value),
);
@override @override
String toString() => "($left * $right)"; String toString() => "($left * $right)";
} }
@@ -378,6 +426,12 @@ class DivExpr extends Expr {
return DivExpr(l, r); return DivExpr(l, r);
} }
@override
Expr substitute(String varName, Expr value) => DivExpr(
left.substitute(varName, value),
right.substitute(varName, value),
);
@override @override
String toString() => "($left / $right)"; String toString() => "($left / $right)";
} }
@@ -429,6 +483,10 @@ class SqrtExpr extends Expr {
return SqrtExpr(i); return SqrtExpr(i);
} }
@override
Expr substitute(String varName, Expr value) =>
SqrtExpr(inner.substitute(varName, value));
@override @override
String toString() => "sqrt($inner)"; String toString() => "sqrt($inner)";
} }
@@ -456,6 +514,10 @@ class CosExpr extends Expr {
return CosExpr(i); return CosExpr(i);
} }
@override
Expr substitute(String varName, Expr value) =>
CosExpr(inner.substitute(varName, value));
@override @override
String toString() => "cos($inner)"; String toString() => "cos($inner)";
} }
@@ -483,6 +545,10 @@ class SinExpr extends Expr {
return SinExpr(i); return SinExpr(i);
} }
@override
Expr substitute(String varName, Expr value) =>
SinExpr(inner.substitute(varName, value));
@override @override
String toString() => "sin($inner)"; String toString() => "sin($inner)";
} }
@@ -510,6 +576,10 @@ class TanExpr extends Expr {
return TanExpr(i); return TanExpr(i);
} }
@override
Expr substitute(String varName, Expr value) =>
TanExpr(inner.substitute(varName, value));
@override @override
String toString() => "tan($inner)"; String toString() => "tan($inner)";
} }

View File

@@ -99,6 +99,13 @@ class Parser {
return TanExpr(inner); return TanExpr(inner);
} }
// 解析变量 (单个字母)
if (RegExp(r'[a-zA-Z]').hasMatch(current)) {
var varName = current;
eat();
return VarExpr(varName);
}
// 解析整数 // 解析整数
var buf = ''; var buf = '';
while (!isEnd && RegExp(r'\d').hasMatch(current)) { while (!isEnd && RegExp(r'\d').hasMatch(current)) {

View File

@@ -3,7 +3,8 @@ import 'package:latext/latext.dart';
import 'package:simple_math_calc/models/calculation_step.dart'; import 'package:simple_math_calc/models/calculation_step.dart';
import 'package:simple_math_calc/solver.dart'; import 'package:simple_math_calc/solver.dart';
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:math_expressions/math_expressions.dart' as math_expressions; import 'package:simple_math_calc/calculator.dart';
import 'package:simple_math_calc/parser.dart';
import 'dart:math'; import 'dart:math';
class CalculatorHomePage extends StatefulWidget { class CalculatorHomePage extends StatefulWidget {
@@ -70,11 +71,8 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
); );
// 解析表达式 // 解析表达式
final parser = math_expressions.ShuntingYardParser(); final parser = Parser(functionExpr);
final expr = parser.parse(functionExpr); final expr = parser.parse();
// 创建变量 x
final x = math_expressions.Variable('x');
// 根据缩放因子动态调整范围和步长 // 根据缩放因子动态调整范围和步长
final range = 10.0 * zoomFactor; final range = 10.0 * zoomFactor;
@@ -84,13 +82,15 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
List<FlSpot> points = []; List<FlSpot> points = [];
for (double i = -range; i <= range; i += step) { for (double i = -range; i <= range; i += step) {
try { try {
final context = math_expressions.ContextModel() // 替换变量 x 为当前值
..bindVariable(x, math_expressions.Number(i)); final substituted = expr.substitute('x', DoubleExpr(i));
final evaluator = math_expressions.RealEvaluator(context); final evaluated = substituted.evaluate();
final y = evaluator.evaluate(expr);
if (y.isFinite && !y.isNaN) { if (evaluated is DoubleExpr) {
points.add(FlSpot(i, y.toDouble())); final y = evaluated.value;
if (y.isFinite && !y.isNaN) {
points.add(FlSpot(i, y));
}
} }
} catch (e) { } catch (e) {
// 跳过无法计算的点 // 跳过无法计算的点

View File

@@ -16,7 +16,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project."> <meta name="description" content="A simple math calculator.">
<!-- iOS meta tags & icons --> <!-- iOS meta tags & icons -->
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">