🐛 Fix case like y=80%*x painting wrongly

This commit is contained in:
2025-09-14 14:46:09 +08:00
parent d26c29613b
commit d652df407f
4 changed files with 52 additions and 14 deletions

View File

@@ -43,23 +43,27 @@ class Parser {
Expr parseMul() { Expr parseMul() {
var expr = parsePow(); var expr = parsePow();
skipSpaces(); skipSpaces();
while (!isEnd && (current == '*' || current == '/')) { while (!isEnd &&
var op = current; (current == '*' ||
eat(); current == '/' ||
var right = parsePow(); current == '%' ||
if (op == '*') { RegExp(r'[a-zA-Z\d]').hasMatch(current) ||
expr = MulExpr(expr, right); 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 { } else {
expr = DivExpr(expr, right); // implicit multiplication
var right = parsePow();
expr = MulExpr(expr, right);
} }
skipSpaces(); skipSpaces();
} }
// Handle percentage operator
skipSpaces();
if (!isEnd && current == '%') {
eat();
expr = PercentExpr(expr);
}
return expr; return expr;
} }

View File

@@ -48,7 +48,30 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
final input = _controller.text.trim(); final input = _controller.text.trim();
final normalizedInput = input.replaceAll(' ', ''); 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)) { if (_solverService.isGraphableExpression(normalizedInput)) {
setState(() { setState(() {
_isFunctionMode = true; _isFunctionMode = true;
@@ -57,6 +80,7 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
return; return;
} }
// 普通表达式求解
setState(() { setState(() {
_isFunctionMode = false; _isFunctionMode = false;
_isLoading = true; _isLoading = true;

View File

@@ -54,6 +54,12 @@ class _GraphCardState extends State<GraphCard> {
(match) => '${match.group(1)}*${match.group(2)}', (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 parser = Parser(functionExpr);
final expr = parser.parse(); final expr = parser.parse();

View File

@@ -130,6 +130,10 @@ void main() {
// 测试无y=前缀的表达式 // 测试无y=前缀的表达式
final noPrefix = solver.prepareFunctionForGraphing('(x-1)(x+3)'); final noPrefix = solver.prepareFunctionForGraphing('(x-1)(x+3)');
expect(noPrefix, 'x^2+2x-3'); expect(noPrefix, 'x^2+2x-3');
// 测试百分比表达式
final percentExpr = solver.prepareFunctionForGraphing('y=80%x');
expect(percentExpr, '80%x');
}); });
}); });
} }