From d652df407f9b267a66a9148e77804972718b653e Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 14 Sep 2025 14:46:09 +0800 Subject: [PATCH] :bug: Fix case like y=80%*x painting wrongly --- lib/parser.dart | 30 +++++++++++++++------------ lib/screens/calculator_home_page.dart | 26 ++++++++++++++++++++++- lib/widgets/graph_card.dart | 6 ++++++ test/solver_test.dart | 4 ++++ 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/lib/parser.dart b/lib/parser.dart index 1d9a750..c3a6993 100644 --- a/lib/parser.dart +++ b/lib/parser.dart @@ -43,23 +43,27 @@ class Parser { Expr parseMul() { var expr = parsePow(); skipSpaces(); - while (!isEnd && (current == '*' || current == '/')) { - var op = current; - eat(); - var right = parsePow(); - if (op == '*') { - expr = MulExpr(expr, right); + while (!isEnd && + (current == '*' || + current == '/' || + current == '%' || + RegExp(r'[a-zA-Z\d]').hasMatch(current) || + current == '(')) { + if (current == '*' || current == '/') { + var op = current; + eat(); + var right = parsePow(); + expr = op == '*' ? MulExpr(expr, right) : DivExpr(expr, right); + } else if (current == '%') { + eat(); + expr = PercentExpr(expr); } else { - expr = DivExpr(expr, right); + // implicit multiplication + var right = parsePow(); + expr = MulExpr(expr, right); } skipSpaces(); } - // Handle percentage operator - skipSpaces(); - if (!isEnd && current == '%') { - eat(); - expr = PercentExpr(expr); - } return expr; } diff --git a/lib/screens/calculator_home_page.dart b/lib/screens/calculator_home_page.dart index 8348f54..9a2a3f7 100644 --- a/lib/screens/calculator_home_page.dart +++ b/lib/screens/calculator_home_page.dart @@ -48,7 +48,30 @@ class _CalculatorHomePageState extends State { final input = _controller.text.trim(); final normalizedInput = input.replaceAll(' ', ''); - // 使用solver检查是否为可绘制的函数表达式 + // 如果当前已经是函数模式,保持函数模式 + if (_isFunctionMode) { + // 重新检查表达式是否仍然可绘制(以防用户修改了表达式) + if (_solverService.isGraphableExpression(normalizedInput)) { + // 保持在函数模式,不做任何改变 + return; + } else { + // 表达式不再可绘制,切换回普通模式 + setState(() { + _isFunctionMode = false; + }); + } + } + + // 检查是否为函数表达式(优先使用简单y=检测) + if (normalizedInput.toLowerCase().startsWith('y=')) { + setState(() { + _isFunctionMode = true; + _result = null; + }); + return; + } + + // 备用检查:使用solver进行更复杂的表达式检测 if (_solverService.isGraphableExpression(normalizedInput)) { setState(() { _isFunctionMode = true; @@ -57,6 +80,7 @@ class _CalculatorHomePageState extends State { return; } + // 普通表达式求解 setState(() { _isFunctionMode = false; _isLoading = true; diff --git a/lib/widgets/graph_card.dart b/lib/widgets/graph_card.dart index 5dea0c9..b535ba3 100644 --- a/lib/widgets/graph_card.dart +++ b/lib/widgets/graph_card.dart @@ -54,6 +54,12 @@ class _GraphCardState extends State { (match) => '${match.group(1)}*${match.group(2)}', ); + // 在 % 和变量或数字之间插入乘号 (如 80%x -> 80%*x) + functionExpr = functionExpr.replaceAllMapped( + RegExp(r'%([a-zA-Z\d])'), + (match) => '%*${match.group(1)}', + ); + // 解析表达式 final parser = Parser(functionExpr); final expr = parser.parse(); diff --git a/test/solver_test.dart b/test/solver_test.dart index 5d657b0..eb03994 100644 --- a/test/solver_test.dart +++ b/test/solver_test.dart @@ -130,6 +130,10 @@ void main() { // 测试无y=前缀的表达式 final noPrefix = solver.prepareFunctionForGraphing('(x-1)(x+3)'); expect(noPrefix, 'x^2+2x-3'); + + // 测试百分比表达式 + final percentExpr = solver.prepareFunctionForGraphing('y=80%x'); + expect(percentExpr, '80%x'); }); }); }