💄 🤔
This commit is contained in:
		
							
								
								
									
										149
									
								
								lib/solver.dart
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								lib/solver.dart
									
									
									
									
									
								
							| @@ -59,15 +59,24 @@ class SolverService { | |||||||
|         stepNumber: 1, |         stepNumber: 1, | ||||||
|         title: '表达式求值', |         title: '表达式求值', | ||||||
|         explanation: '这是一个标准的数学表达式,我们将直接计算其结果。', |         explanation: '这是一个标准的数学表达式,我们将直接计算其结果。', | ||||||
|         formula: input, |         formula: '\$\$$input\$\$', | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     GrammarParser p = GrammarParser(); |     // 预处理平方根符号 | ||||||
|     Expression exp = p.parse(input); |     final processedInput = _preprocessSqrt(input); | ||||||
|     final result = RealEvaluator().evaluate(exp); |  | ||||||
|  |  | ||||||
|     return CalculationResult(steps: steps, finalAnswer: result.toString()); |     GrammarParser p = GrammarParser(); | ||||||
|  |     Expression exp = p.parse(processedInput); | ||||||
|  |     final result = RealEvaluator().evaluate(exp).toDouble(); | ||||||
|  |  | ||||||
|  |     // 尝试将结果格式化为几倍根号的形式 | ||||||
|  |     final formattedResult = _formatSqrtResult(result); | ||||||
|  |  | ||||||
|  |     return CalculationResult( | ||||||
|  |       steps: steps, | ||||||
|  |       finalAnswer: '\$\$$formattedResult\$\$', | ||||||
|  |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /// 2. 求解一元一次方程 |   /// 2. 求解一元一次方程 | ||||||
| @@ -422,6 +431,81 @@ ${b1}y &= ${c1 - a1 * x} | |||||||
|  |  | ||||||
|   /// ---- 辅助函数 ---- |   /// ---- 辅助函数 ---- | ||||||
|  |  | ||||||
|  |   /// 将数值结果格式化为几倍根号的形式 | ||||||
|  |   String _formatSqrtResult(double result) { | ||||||
|  |     // 处理负数 | ||||||
|  |     if (result < 0) { | ||||||
|  |       return '-${_formatSqrtResult(-result)}'; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 处理零 | ||||||
|  |     if (result == 0) return '0'; | ||||||
|  |  | ||||||
|  |     // 检查是否接近整数 | ||||||
|  |     final rounded = result.round(); | ||||||
|  |     if ((result - rounded).abs() < 1e-10) { | ||||||
|  |       return rounded.toString(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 计算 result 的平方,看它是否接近整数 | ||||||
|  |     final squared = result * result; | ||||||
|  |     final squaredRounded = squared.round(); | ||||||
|  |  | ||||||
|  |     // 如果 squared 接近整数,说明 result 是某个数的平方根 | ||||||
|  |     if ((squared - squaredRounded).abs() < 1e-6) { | ||||||
|  |       // 寻找最大的完全平方数因子 | ||||||
|  |       int maxSquareFactor = 1; | ||||||
|  |       for (int i = 2; i * i <= squaredRounded; i++) { | ||||||
|  |         if (squaredRounded % (i * i) == 0) { | ||||||
|  |           maxSquareFactor = i * i; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       final coefficient = sqrt(maxSquareFactor).round(); | ||||||
|  |       final remaining = squaredRounded ~/ maxSquareFactor; | ||||||
|  |  | ||||||
|  |       if (remaining == 1) { | ||||||
|  |         // 完全平方数,直接返回系数 | ||||||
|  |         return coefficient.toString(); | ||||||
|  |       } else if (coefficient == 1) { | ||||||
|  |         return '\\sqrt{$remaining}'; | ||||||
|  |       } else { | ||||||
|  |         return '$coefficient\\sqrt{$remaining}'; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 如果不是平方根的结果,返回原始数值(保留几位小数) | ||||||
|  |     return result | ||||||
|  |         .toStringAsFixed(6) | ||||||
|  |         .replaceAll(RegExp(r'\.0+$'), '') | ||||||
|  |         .replaceAll(RegExp(r'\.$'), ''); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /// 预处理平方根表示法,将 \sqrt{expr} 转换为 sqrt(expr) | ||||||
|  |   String _preprocessSqrt(String input) { | ||||||
|  |     // 使用正则表达式替换 \sqrt{expr} 为 sqrt(expr) | ||||||
|  |     // 处理嵌套的情况,使用循环直到没有更多匹配 | ||||||
|  |     String result = input; | ||||||
|  |     int maxIterations = 10; // 防止无限循环 | ||||||
|  |     int iterationCount = 0; | ||||||
|  |  | ||||||
|  |     while (iterationCount < maxIterations) { | ||||||
|  |       String oldResult = result; | ||||||
|  |       result = result.replaceAllMapped( | ||||||
|  |         RegExp(r'\\sqrt\{([^}]+)\}'), | ||||||
|  |         (match) => 'sqrt(${match.group(1)})', | ||||||
|  |       ); | ||||||
|  |       if (result == oldResult) break; | ||||||
|  |       iterationCount++; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (iterationCount >= maxIterations) { | ||||||
|  |       throw Exception('平方根表达式过于复杂,请简化输入。'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   String _expandExpressions(String input) { |   String _expandExpressions(String input) { | ||||||
|     String result = input; |     String result = input; | ||||||
|     int maxIterations = 10; // Prevent infinite loops |     int maxIterations = 10; // Prevent infinite loops | ||||||
| @@ -544,29 +628,68 @@ ${b1}y &= ${c1 - a1 * x} | |||||||
|  |  | ||||||
|   Map<int, double> _parsePolynomial(String side) { |   Map<int, double> _parsePolynomial(String side) { | ||||||
|     final coeffs = <int, double>{}; |     final coeffs = <int, double>{}; | ||||||
|  |     // 扩展模式以支持 sqrt 函数 | ||||||
|     final pattern = RegExp( |     final pattern = RegExp( | ||||||
|       r'([+-]?(?:\d*\.?\d*)?)x(?:\^(\d+))?|([+-]?\d*\.?\d+)', |       r'([+-]?(?:\d*\.?\d*|sqrt\(\d+\)))x(?:\^(\d+))?|([+-]?(?:\d*\.?\d*|sqrt\(\d+\)))', | ||||||
|     ); |     ); | ||||||
|     var s = side.startsWith('+') || side.startsWith('-') ? side : '+$side'; |     var s = side.startsWith('+') || side.startsWith('-') ? side : '+$side'; | ||||||
|  |  | ||||||
|     for (final match in pattern.allMatches(s)) { |     for (final match in pattern.allMatches(s)) { | ||||||
|       if (match.group(3) != null) { |       if (match.group(3) != null) { | ||||||
|         coeffs[0] = (coeffs[0] ?? 0) + double.parse(match.group(3)!); |         // 常数项 | ||||||
|  |         final constStr = match.group(3)!; | ||||||
|  |         final constValue = _parseCoefficientWithSqrt(constStr); | ||||||
|  |         coeffs[0] = (coeffs[0] ?? 0) + constValue; | ||||||
|       } else { |       } else { | ||||||
|  |         // x 的幂次项 | ||||||
|         int power = match.group(2) != null ? int.parse(match.group(2)!) : 1; |         int power = match.group(2) != null ? int.parse(match.group(2)!) : 1; | ||||||
|         String coeffStr = match.group(1) ?? '+'; |         String coeffStr = match.group(1) ?? '+'; | ||||||
|         double coeff = 1.0; |         final coeff = _parseCoefficientWithSqrt(coeffStr); | ||||||
|         if (coeffStr.isNotEmpty && coeffStr != '+') { |  | ||||||
|           coeff = coeffStr == '-' ? -1.0 : double.parse(coeffStr); |  | ||||||
|         } else if (coeffStr == '-') { |  | ||||||
|           coeff = -1.0; |  | ||||||
|         } |  | ||||||
|         coeffs[power] = (coeffs[power] ?? 0) + coeff; |         coeffs[power] = (coeffs[power] ?? 0) + coeff; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     return coeffs; |     return coeffs; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /// 解析包含 sqrt 函数的系数 | ||||||
|  |   double _parseCoefficientWithSqrt(String coeffStr) { | ||||||
|  |     if (coeffStr.isEmpty || coeffStr == '+') return 1.0; | ||||||
|  |     if (coeffStr == '-') return -1.0; | ||||||
|  |  | ||||||
|  |     // 检查是否包含 sqrt 函数 | ||||||
|  |     final sqrtMatch = RegExp(r'sqrt\((\d+)\)').firstMatch(coeffStr); | ||||||
|  |     if (sqrtMatch != null) { | ||||||
|  |       final innerValue = int.parse(sqrtMatch.group(1)!); | ||||||
|  |  | ||||||
|  |       // 对于完全平方数,直接返回整数结果 | ||||||
|  |       final sqrtValue = sqrt(innerValue.toDouble()); | ||||||
|  |       final rounded = sqrtValue.round(); | ||||||
|  |       if ((sqrtValue - rounded).abs() < 1e-10) { | ||||||
|  |         // 检查是否有系数 | ||||||
|  |         final coeffPart = coeffStr.replaceFirst(sqrtMatch.group(0)!, ''); | ||||||
|  |         if (coeffPart.isEmpty) return rounded.toDouble(); | ||||||
|  |         if (coeffPart == '-') return -rounded.toDouble(); | ||||||
|  |  | ||||||
|  |         final coeff = double.parse(coeffPart); | ||||||
|  |         return coeff * rounded; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       // 对于非完全平方数,计算数值但保持高精度 | ||||||
|  |       final nonPerfectSqrtValue = sqrt(innerValue.toDouble()); | ||||||
|  |  | ||||||
|  |       // 检查是否有系数 | ||||||
|  |       final coeffPart = coeffStr.replaceFirst(sqrtMatch.group(0)!, ''); | ||||||
|  |       if (coeffPart.isEmpty) return nonPerfectSqrtValue; | ||||||
|  |       if (coeffPart == '-') return -nonPerfectSqrtValue; | ||||||
|  |  | ||||||
|  |       final coeff = double.parse(coeffPart); | ||||||
|  |       return coeff * nonPerfectSqrtValue; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 普通数值 | ||||||
|  |     return double.parse(coeffStr); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   List<double> _parseTwoVariableLinear(String equation) { |   List<double> _parseTwoVariableLinear(String equation) { | ||||||
|     final parts = equation.split('='); |     final parts = equation.split('='); | ||||||
|     if (parts.length != 2) throw Exception("方程 $equation 格式错误"); |     if (parts.length != 2) throw Exception("方程 $equation 格式错误"); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user