🐛 Fix solver expand expression
This commit is contained in:
178
lib/solver.dart
178
lib/solver.dart
@@ -629,7 +629,7 @@ ${b1}y &= ${c1 - a1 * x.toDouble()}
|
||||
|
||||
final expanded =
|
||||
'${newA}x^2${newB >= 0 ? '+' : ''}${newB}x${newC >= 0 ? '+' : ''}$newC';
|
||||
result = result.replaceFirst(powerMatch.group(0)!, '($expanded)');
|
||||
result = result.replaceFirst(powerMatch.group(0)!, expanded);
|
||||
iterationCount++;
|
||||
continue;
|
||||
}
|
||||
@@ -700,7 +700,7 @@ ${b1}y &= ${c1 - a1 * x.toDouble()}
|
||||
: newA == -1
|
||||
? '-'
|
||||
: newA}x^2${newB >= 0 ? '+' : ''}${newB}x${newC >= 0 ? '+' : ''}$newC';
|
||||
result = result.replaceFirst(termFactorMatch.group(0)!, '($expanded)');
|
||||
result = result.replaceFirst(termFactorMatch.group(0)!, expanded);
|
||||
iterationCount++;
|
||||
continue;
|
||||
}
|
||||
@@ -713,6 +713,9 @@ ${b1}y &= ${c1 - a1 * x.toDouble()}
|
||||
throw Exception('表达式展开过于复杂,请简化输入。');
|
||||
}
|
||||
|
||||
// 清理展开后的表达式格式
|
||||
result = _cleanExpandedExpression(result);
|
||||
|
||||
// 检查是否为方程(包含等号),如果是的话,将右边的常数项移到左边
|
||||
if (result.contains('=')) {
|
||||
final parts = result.split('=');
|
||||
@@ -1177,13 +1180,35 @@ ${b1}y &= ${c1 - a1 * x.toDouble()}
|
||||
|
||||
final parts = result.split('=');
|
||||
if (parts.length == 2) {
|
||||
// Check if the equation is already in standard polynomial form
|
||||
// If it doesn't contain parentheses and looks like a standard polynomial,
|
||||
// return it as-is to avoid unnecessary parsing
|
||||
final leftSide = parts[0];
|
||||
final rightSide = parts[1];
|
||||
|
||||
// If left side is a standard polynomial (no parentheses, only x^2, x, and constants)
|
||||
// and right side is 0, return the original
|
||||
if (_isStandardPolynomial(leftSide) &&
|
||||
(rightSide == '0' || rightSide.isEmpty)) {
|
||||
result = '$leftSide=0';
|
||||
return '\$\$$result\$\$';
|
||||
}
|
||||
|
||||
try {
|
||||
final leftParser = Parser(parts[0]);
|
||||
final leftExpr = leftParser.parse();
|
||||
final rightParser = Parser(parts[1]);
|
||||
final rightExpr = rightParser.parse();
|
||||
result =
|
||||
'${leftExpr.toString().replaceAll('*', '\\cdot')}=${rightExpr.toString().replaceAll('*', '\\cdot')}';
|
||||
|
||||
// Get the string representation and clean it up
|
||||
String leftStr = leftExpr.toString().replaceAll('*', '\\cdot');
|
||||
String rightStr = rightExpr.toString().replaceAll('*', '\\cdot');
|
||||
|
||||
// Clean up unnecessary parentheses
|
||||
leftStr = _cleanParentheses(leftStr);
|
||||
rightStr = _cleanParentheses(rightStr);
|
||||
|
||||
result = '$leftStr=$rightStr';
|
||||
} catch (e) {
|
||||
// Fallback to original if parsing fails
|
||||
result = result.replaceAll('sqrt(', '\\sqrt{');
|
||||
@@ -1193,7 +1218,12 @@ ${b1}y &= ${c1 - a1 * x.toDouble()}
|
||||
try {
|
||||
final parser = Parser(result.split('=')[0]);
|
||||
final expr = parser.parse();
|
||||
result = '${expr.toString().replaceAll('*', '\\cdot')}=0';
|
||||
|
||||
// Get the string representation and clean it up
|
||||
String exprStr = expr.toString().replaceAll('*', '\\cdot');
|
||||
exprStr = _cleanParentheses(exprStr);
|
||||
|
||||
result = '$exprStr=0';
|
||||
} catch (e) {
|
||||
// Fallback
|
||||
result = result.replaceAll('sqrt(', '\\sqrt{');
|
||||
@@ -1204,6 +1234,101 @@ ${b1}y &= ${c1 - a1 * x.toDouble()}
|
||||
return '\$\$$result\$\$';
|
||||
}
|
||||
|
||||
/// 检查字符串是否为标准多项式形式(不含括号,只有x^2、x和常数项)
|
||||
bool _isStandardPolynomial(String expr) {
|
||||
// Remove spaces
|
||||
final cleanExpr = expr.replaceAll(' ', '');
|
||||
|
||||
// If it contains parentheses, it's not standard
|
||||
if (cleanExpr.contains('(') || cleanExpr.contains(')')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if it matches the pattern of a standard polynomial
|
||||
// Should only contain: digits, x, ^, +, -, and spaces (already removed)
|
||||
final validChars = RegExp(r'^[0-9x\^\+\-\.]*$');
|
||||
if (!validChars.hasMatch(cleanExpr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Should not have complex expressions like x*x or 2x*3
|
||||
if (cleanExpr.contains('*') || cleanExpr.contains('/')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Should have proper x^2 format (not xx or x2)
|
||||
if (cleanExpr.contains('x^2') ||
|
||||
cleanExpr.contains('x^3') ||
|
||||
cleanExpr.contains('x^4')) {
|
||||
// This is likely a polynomial
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for simple terms like x, 2x, x+1, etc.
|
||||
final termPattern = RegExp(
|
||||
r'^[+-]?(?:\d*\.?\d*)?x?(?:\^\d+)?(?:[+-][+-]?(?:\d*\.?\d*)?x?(?:\^\d+)?)*$',
|
||||
);
|
||||
return termPattern.hasMatch(cleanExpr);
|
||||
}
|
||||
|
||||
/// 清理不必要的括号
|
||||
String _cleanParentheses(String expr) {
|
||||
// 移除最外层的括号,如果它们不影响运算顺序
|
||||
if (expr.startsWith('(') && expr.endsWith(')')) {
|
||||
String inner = expr.substring(1, expr.length - 1);
|
||||
|
||||
// 检查移除括号是否会改变含义
|
||||
// 简单检查:如果内部没有运算符,或者只有加减号,可以移除
|
||||
if (!inner.contains('+') &&
|
||||
!inner.contains('-') &&
|
||||
!inner.contains('*') &&
|
||||
!inner.contains('/')) {
|
||||
return inner;
|
||||
}
|
||||
|
||||
// 如果内部表达式是简单的,可以移除括号
|
||||
// 例如:(x+1) 可以变成 x+1, 但 (x+1)*(x-1) 不能移除
|
||||
final operators = RegExp(r'[+\-*/]');
|
||||
final matches = operators.allMatches(inner).toList();
|
||||
|
||||
// 如果只有一个运算符且是加减号,可以移除
|
||||
if (matches.length == 1 && (inner.contains('+') || inner.contains('-'))) {
|
||||
return inner;
|
||||
}
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
/// 清理展开后的表达式格式
|
||||
String _cleanExpandedExpression(String expr) {
|
||||
String result = expr;
|
||||
|
||||
// 移除不必要的.0后缀
|
||||
result = result.replaceAll('.0', '');
|
||||
|
||||
// 移除+0和-0
|
||||
result = result.replaceAll('+0', '');
|
||||
result = result.replaceAll('-0', '');
|
||||
|
||||
// 简化系数为1的情况
|
||||
result = result.replaceAll('1x^2', 'x^2');
|
||||
result = result.replaceAll('1x', 'x');
|
||||
|
||||
// 移除开头的+号
|
||||
if (result.startsWith('+')) {
|
||||
result = result.substring(1);
|
||||
}
|
||||
|
||||
// 处理连续的运算符
|
||||
result = result.replaceAll('++', '+');
|
||||
result = result.replaceAll('+-', '-');
|
||||
result = result.replaceAll('-+', '-');
|
||||
result = result.replaceAll('--', '+');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// 解析多项式,保持符号形式
|
||||
Map<int, String> _parsePolynomialSymbolic(String side) {
|
||||
final coeffs = <int, String>{};
|
||||
@@ -1396,4 +1521,47 @@ ${b1}y &= ${c1 - a1 * x.toDouble()}
|
||||
|
||||
return Rational(numerator, denominator);
|
||||
}
|
||||
|
||||
/// 测试方法:验证修复效果
|
||||
void testParenthesesFix() {
|
||||
print('=== 测试括号修复效果 ===');
|
||||
|
||||
// 测试案例1: 已经标准化的方程
|
||||
final test1 = 'x^2+4x-8=0';
|
||||
print('测试输入: $test1');
|
||||
final result1 = solve(test1);
|
||||
print('整理方程步骤:');
|
||||
result1.steps.forEach((step) {
|
||||
if (step.title == '整理方程') {
|
||||
print(' 公式: ${step.formula}');
|
||||
}
|
||||
});
|
||||
print('预期: x^2+4x-8=0 (无括号)');
|
||||
print('');
|
||||
|
||||
// 测试案例2: 需要展开的方程
|
||||
final test2 = '(x+2)^2=x^2+4x+4';
|
||||
print('测试输入: $test2');
|
||||
final result2 = solve(test2);
|
||||
print('整理方程步骤:');
|
||||
result2.steps.forEach((step) {
|
||||
if (step.title == '整理方程') {
|
||||
print(' 公式: ${step.formula}');
|
||||
}
|
||||
});
|
||||
print('预期: 展开后无不必要的括号');
|
||||
print('');
|
||||
|
||||
// 测试案例3: 因式分解
|
||||
final test3 = '(x+1)(x-1)=x^2-1';
|
||||
print('测试输入: $test3');
|
||||
final result3 = solve(test3);
|
||||
print('整理方程步骤:');
|
||||
result3.steps.forEach((step) {
|
||||
if (step.title == '整理方程') {
|
||||
print(' 公式: ${step.formula}');
|
||||
}
|
||||
});
|
||||
print('预期: 展开后无不必要的括号');
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user