♻️ Replace the math expressions with own calculator
This commit is contained in:
		| @@ -7,6 +7,9 @@ abstract class Expr { | ||||
|   /// 新增:对表达式进行“求值/数值化”——尽可能把可算的部分算出来 | ||||
|   Expr evaluate(); | ||||
|  | ||||
|   /// Substitute variable with value | ||||
|   Expr substitute(String varName, Expr value); | ||||
|  | ||||
|   @override | ||||
|   String toString(); | ||||
|  | ||||
| @@ -27,6 +30,9 @@ class IntExpr extends Expr { | ||||
|   @override | ||||
|   Expr evaluate() => this; | ||||
|  | ||||
|   @override | ||||
|   Expr substitute(String varName, Expr value) => this; | ||||
|  | ||||
|   @override | ||||
|   String toString() => value.toString(); | ||||
| } | ||||
| @@ -42,10 +48,31 @@ class DoubleExpr extends Expr { | ||||
|   @override | ||||
|   Expr evaluate() => this; | ||||
|  | ||||
|   @override | ||||
|   Expr substitute(String varName, Expr value) => this; | ||||
|  | ||||
|   @override | ||||
|   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 === | ||||
| class FractionExpr extends Expr { | ||||
|   final int numerator; | ||||
| @@ -74,6 +101,9 @@ class FractionExpr extends Expr { | ||||
|   @override | ||||
|   Expr evaluate() => simplify(); | ||||
|  | ||||
|   @override | ||||
|   Expr substitute(String varName, Expr value) => this; | ||||
|  | ||||
|   @override | ||||
|   String toString() => "$numerator/$denominator"; | ||||
| } | ||||
| @@ -150,6 +180,12 @@ class AddExpr extends Expr { | ||||
|     return AddExpr(l, r); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Expr substitute(String varName, Expr value) => AddExpr( | ||||
|     left.substitute(varName, value), | ||||
|     right.substitute(varName, value), | ||||
|   ); | ||||
|  | ||||
|   @override | ||||
|   String toString() => "($left + $right)"; | ||||
| } | ||||
| @@ -213,6 +249,12 @@ class SubExpr extends Expr { | ||||
|     return SubExpr(l, r); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Expr substitute(String varName, Expr value) => SubExpr( | ||||
|     left.substitute(varName, value), | ||||
|     right.substitute(varName, value), | ||||
|   ); | ||||
|  | ||||
|   @override | ||||
|   String toString() => "($left - $right)"; | ||||
| } | ||||
| @@ -296,6 +338,12 @@ class MulExpr extends Expr { | ||||
|     return MulExpr(l, r); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Expr substitute(String varName, Expr value) => MulExpr( | ||||
|     left.substitute(varName, value), | ||||
|     right.substitute(varName, value), | ||||
|   ); | ||||
|  | ||||
|   @override | ||||
|   String toString() => "($left * $right)"; | ||||
| } | ||||
| @@ -378,6 +426,12 @@ class DivExpr extends Expr { | ||||
|     return DivExpr(l, r); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Expr substitute(String varName, Expr value) => DivExpr( | ||||
|     left.substitute(varName, value), | ||||
|     right.substitute(varName, value), | ||||
|   ); | ||||
|  | ||||
|   @override | ||||
|   String toString() => "($left / $right)"; | ||||
| } | ||||
| @@ -429,6 +483,10 @@ class SqrtExpr extends Expr { | ||||
|     return SqrtExpr(i); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Expr substitute(String varName, Expr value) => | ||||
|       SqrtExpr(inner.substitute(varName, value)); | ||||
|  | ||||
|   @override | ||||
|   String toString() => "sqrt($inner)"; | ||||
| } | ||||
| @@ -456,6 +514,10 @@ class CosExpr extends Expr { | ||||
|     return CosExpr(i); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Expr substitute(String varName, Expr value) => | ||||
|       CosExpr(inner.substitute(varName, value)); | ||||
|  | ||||
|   @override | ||||
|   String toString() => "cos($inner)"; | ||||
| } | ||||
| @@ -483,6 +545,10 @@ class SinExpr extends Expr { | ||||
|     return SinExpr(i); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Expr substitute(String varName, Expr value) => | ||||
|       SinExpr(inner.substitute(varName, value)); | ||||
|  | ||||
|   @override | ||||
|   String toString() => "sin($inner)"; | ||||
| } | ||||
| @@ -510,6 +576,10 @@ class TanExpr extends Expr { | ||||
|     return TanExpr(i); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Expr substitute(String varName, Expr value) => | ||||
|       TanExpr(inner.substitute(varName, value)); | ||||
|  | ||||
|   @override | ||||
|   String toString() => "tan($inner)"; | ||||
| } | ||||
|   | ||||
| @@ -99,6 +99,13 @@ class Parser { | ||||
|       return TanExpr(inner); | ||||
|     } | ||||
|  | ||||
|     // 解析变量 (单个字母) | ||||
|     if (RegExp(r'[a-zA-Z]').hasMatch(current)) { | ||||
|       var varName = current; | ||||
|       eat(); | ||||
|       return VarExpr(varName); | ||||
|     } | ||||
|  | ||||
|     // 解析整数 | ||||
|     var buf = ''; | ||||
|     while (!isEnd && RegExp(r'\d').hasMatch(current)) { | ||||
|   | ||||
| @@ -3,7 +3,8 @@ import 'package:latext/latext.dart'; | ||||
| import 'package:simple_math_calc/models/calculation_step.dart'; | ||||
| import 'package:simple_math_calc/solver.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'; | ||||
|  | ||||
| class CalculatorHomePage extends StatefulWidget { | ||||
| @@ -70,11 +71,8 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> { | ||||
|       ); | ||||
|  | ||||
|       // 解析表达式 | ||||
|       final parser = math_expressions.ShuntingYardParser(); | ||||
|       final expr = parser.parse(functionExpr); | ||||
|  | ||||
|       // 创建变量 x | ||||
|       final x = math_expressions.Variable('x'); | ||||
|       final parser = Parser(functionExpr); | ||||
|       final expr = parser.parse(); | ||||
|  | ||||
|       // 根据缩放因子动态调整范围和步长 | ||||
|       final range = 10.0 * zoomFactor; | ||||
| @@ -84,13 +82,15 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> { | ||||
|       List<FlSpot> points = []; | ||||
|       for (double i = -range; i <= range; i += step) { | ||||
|         try { | ||||
|           final context = math_expressions.ContextModel() | ||||
|             ..bindVariable(x, math_expressions.Number(i)); | ||||
|           final evaluator = math_expressions.RealEvaluator(context); | ||||
|           final y = evaluator.evaluate(expr); | ||||
|           // 替换变量 x 为当前值 | ||||
|           final substituted = expr.substitute('x', DoubleExpr(i)); | ||||
|           final evaluated = substituted.evaluate(); | ||||
|  | ||||
|           if (y.isFinite && !y.isNaN) { | ||||
|             points.add(FlSpot(i, y.toDouble())); | ||||
|           if (evaluated is DoubleExpr) { | ||||
|             final y = evaluated.value; | ||||
|             if (y.isFinite && !y.isNaN) { | ||||
|               points.add(FlSpot(i, y)); | ||||
|             } | ||||
|           } | ||||
|         } catch (e) { | ||||
|           // 跳过无法计算的点 | ||||
|   | ||||
| @@ -16,7 +16,7 @@ | ||||
|  | ||||
|   <meta charset="UTF-8"> | ||||
|   <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 --> | ||||
|   <meta name="mobile-web-app-capable" content="yes"> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user