🐛 Fix case like y=80%*x painting wrongly
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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();
|
||||||
|
@@ -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');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user