♻️ Move the sin / cos / tan to the calcualtor
This commit is contained in:
		| @@ -1,5 +1,6 @@ | |||||||
| // === 在 abstract class Expr 中添加声明 === | // === 在 abstract class Expr 中添加声明 === | ||||||
| import 'dart:math' show sqrt, cos, sin, tan, pow; | import 'dart:math' show sqrt, cos, sin, tan, pow; | ||||||
|  | import 'parser.dart'; | ||||||
|  |  | ||||||
| abstract class Expr { | abstract class Expr { | ||||||
|   Expr simplify(); |   Expr simplify(); | ||||||
| @@ -689,5 +690,159 @@ _SqrtTerm? _asSqrtTerm(Expr e) { | |||||||
|   return null; |   return null; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// 获取精确三角函数结果 | ||||||
|  | String? getExactTrigResult(String input) { | ||||||
|  |   final cleanInput = input.replaceAll(' ', '').toLowerCase(); | ||||||
|  |  | ||||||
|  |   // 匹配 sin(角度) 模式 | ||||||
|  |   final sinMatch = RegExp(r'^sin\((\d+(?:\+\d+)*)\)$').firstMatch(cleanInput); | ||||||
|  |   if (sinMatch != null) { | ||||||
|  |     final angleExpr = sinMatch.group(1)!; | ||||||
|  |     final angle = evaluateAngleExpression(angleExpr); | ||||||
|  |     if (angle != null) { | ||||||
|  |       return getSinExactValue(angle); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // 匹配 cos(角度) 模式 | ||||||
|  |   final cosMatch = RegExp(r'^cos\((\d+(?:\+\d+)*)\)$').firstMatch(cleanInput); | ||||||
|  |   if (cosMatch != null) { | ||||||
|  |     final angleExpr = cosMatch.group(1)!; | ||||||
|  |     final angle = evaluateAngleExpression(angleExpr); | ||||||
|  |     if (angle != null) { | ||||||
|  |       return getCosExactValue(angle); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // 匹配 tan(角度) 模式 | ||||||
|  |   final tanMatch = RegExp(r'^tan\((\d+(?:\+\d+)*)\)$').firstMatch(cleanInput); | ||||||
|  |   if (tanMatch != null) { | ||||||
|  |     final angleExpr = tanMatch.group(1)!; | ||||||
|  |     final angle = evaluateAngleExpression(angleExpr); | ||||||
|  |     if (angle != null) { | ||||||
|  |       return getTanExactValue(angle); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return null; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// 获取 sin 的精确值 | ||||||
|  | String? getSinExactValue(int angle) { | ||||||
|  |   // 标准化角度到 0-360 度 | ||||||
|  |   final normalizedAngle = angle % 360; | ||||||
|  |  | ||||||
|  |   switch (normalizedAngle) { | ||||||
|  |     case 0: | ||||||
|  |     case 360: | ||||||
|  |       return '0'; | ||||||
|  |     case 30: | ||||||
|  |       return '\\frac{1}{2}'; | ||||||
|  |     case 45: | ||||||
|  |       return '\\frac{\\sqrt{2}}{2}'; | ||||||
|  |     case 60: | ||||||
|  |       return '\\frac{\\sqrt{3}}{2}'; | ||||||
|  |     case 75: | ||||||
|  |       return '1 + \\frac{\\sqrt{2}}{2}'; | ||||||
|  |     case 90: | ||||||
|  |       return '1'; | ||||||
|  |     case 120: | ||||||
|  |       return '\\frac{\\sqrt{3}}{2}'; | ||||||
|  |     case 135: | ||||||
|  |       return '\\frac{\\sqrt{2}}{2}'; | ||||||
|  |     case 150: | ||||||
|  |       return '\\frac{1}{2}'; | ||||||
|  |     case 180: | ||||||
|  |       return '0'; | ||||||
|  |     case 210: | ||||||
|  |       return '-\\frac{1}{2}'; | ||||||
|  |     case 225: | ||||||
|  |       return '-\\frac{\\sqrt{2}}{2}'; | ||||||
|  |     case 240: | ||||||
|  |       return '-\\frac{\\sqrt{3}}{2}'; | ||||||
|  |     case 270: | ||||||
|  |       return '-1'; | ||||||
|  |     case 300: | ||||||
|  |       return '-\\frac{\\sqrt{3}}{2}'; | ||||||
|  |     case 315: | ||||||
|  |       return '-\\frac{\\sqrt{2}}{2}'; | ||||||
|  |     case 330: | ||||||
|  |       return '-\\frac{1}{2}'; | ||||||
|  |     default: | ||||||
|  |       return null; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// 获取 cos 的精确值 | ||||||
|  | String? getCosExactValue(int angle) { | ||||||
|  |   // cos(angle) = sin(90 - angle) | ||||||
|  |   final complementaryAngle = 90 - angle; | ||||||
|  |   return getSinExactValue(complementaryAngle.abs()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// 获取 tan 的精确值 | ||||||
|  | String? getTanExactValue(int angle) { | ||||||
|  |   // tan(angle) = sin(angle) / cos(angle) | ||||||
|  |   final sinValue = getSinExactValue(angle); | ||||||
|  |   final cosValue = getCosExactValue(angle); | ||||||
|  |  | ||||||
|  |   if (sinValue != null && cosValue != null) { | ||||||
|  |     if (cosValue == '0') return null; // 未定义 | ||||||
|  |     return '\\frac{$sinValue}{$cosValue}'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return null; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// 将数值结果格式化为几倍根号的形式 | ||||||
|  | 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'\.$'), ''); | ||||||
|  | } | ||||||
|  |  | ||||||
| /// 辗转相除法求 gcd | /// 辗转相除法求 gcd | ||||||
| int _gcd(int a, int b) => b == 0 ? a : _gcd(b, a % b); | int _gcd(int a, int b) => b == 0 ? a : _gcd(b, a % b); | ||||||
|   | |||||||
| @@ -134,3 +134,41 @@ class Parser { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// 计算角度表达式(如 30+45 = 75) | ||||||
|  | int? evaluateAngleExpression(String expr) { | ||||||
|  |   final parts = expr.split('+'); | ||||||
|  |   int sum = 0; | ||||||
|  |   for (final part in parts) { | ||||||
|  |     final num = int.tryParse(part.trim()); | ||||||
|  |     if (num == null) return null; | ||||||
|  |     sum += num; | ||||||
|  |   } | ||||||
|  |   return sum; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// 将三角函数的参数从度转换为弧度 | ||||||
|  | String convertTrigToRadians(String input) { | ||||||
|  |   String result = input; | ||||||
|  |  | ||||||
|  |   // 正则表达式匹配三角函数调用,如 sin(30), cos(45), tan(60) | ||||||
|  |   final trigPattern = RegExp( | ||||||
|  |     r'(sin|cos|tan|asin|acos|atan)\s*\(\s*([^)]+)\s*\)', | ||||||
|  |     caseSensitive: false, | ||||||
|  |   ); | ||||||
|  |  | ||||||
|  |   result = result.replaceAllMapped(trigPattern, (match) { | ||||||
|  |     final func = match.group(1)!; | ||||||
|  |     final arg = match.group(2)!; | ||||||
|  |  | ||||||
|  |     // 如果参数已经是弧度相关的表达式(包含 pi 或 π),则不转换 | ||||||
|  |     if (arg.contains('pi') || arg.contains('π') || arg.contains('rad')) { | ||||||
|  |       return '$func($arg)'; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 将度数转换为弧度:度 * π / 180 | ||||||
|  |     return '$func(($arg)*(π/180))'; | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   return result; | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										198
									
								
								lib/solver.dart
									
									
									
									
									
								
							
							
						
						
									
										198
									
								
								lib/solver.dart
									
									
									
									
									
								
							| @@ -67,7 +67,7 @@ class SolverService { | |||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     // 检查是否为特殊三角函数值,可以返回精确结果 |     // 检查是否为特殊三角函数值,可以返回精确结果 | ||||||
|     final exactTrigResult = _getExactTrigResult(input); |     final exactTrigResult = getExactTrigResult(input); | ||||||
|     if (exactTrigResult != null) { |     if (exactTrigResult != null) { | ||||||
|       return CalculationResult( |       return CalculationResult( | ||||||
|         steps: steps, |         steps: steps, | ||||||
| @@ -76,7 +76,7 @@ class SolverService { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // 预处理输入,将三角函数的参数从度转换为弧度 |     // 预处理输入,将三角函数的参数从度转换为弧度 | ||||||
|     String processedInput = _convertTrigToRadians(input); |     String processedInput = convertTrigToRadians(input); | ||||||
|  |  | ||||||
|     try { |     try { | ||||||
|       // 使用自定义解析器解析表达式 |       // 使用自定义解析器解析表达式 | ||||||
| @@ -104,7 +104,7 @@ class SolverService { | |||||||
|       } |       } | ||||||
|  |  | ||||||
|       // 尝试将结果格式化为几倍根号的形式 |       // 尝试将结果格式化为几倍根号的形式 | ||||||
|       final formattedResult = _formatSqrtResult(result); |       final formattedResult = formatSqrtResult(result); | ||||||
|  |  | ||||||
|       return CalculationResult( |       return CalculationResult( | ||||||
|         steps: steps, |         steps: steps, | ||||||
| @@ -513,198 +513,6 @@ ${b1}y &= ${c1 - a1 * x.toDouble()} | |||||||
|  |  | ||||||
|   /// ---- 辅助函数 ---- |   /// ---- 辅助函数 ---- | ||||||
|  |  | ||||||
|   /// 获取精确三角函数结果 |  | ||||||
|   String? _getExactTrigResult(String input) { |  | ||||||
|     final cleanInput = input.replaceAll(' ', '').toLowerCase(); |  | ||||||
|  |  | ||||||
|     // 匹配 sin(角度) 模式 |  | ||||||
|     final sinMatch = RegExp(r'^sin\((\d+(?:\+\d+)*)\)$').firstMatch(cleanInput); |  | ||||||
|     if (sinMatch != null) { |  | ||||||
|       final angleExpr = sinMatch.group(1)!; |  | ||||||
|       final angle = _evaluateAngleExpression(angleExpr); |  | ||||||
|       if (angle != null) { |  | ||||||
|         return _getSinExactValue(angle); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // 匹配 cos(角度) 模式 |  | ||||||
|     final cosMatch = RegExp(r'^cos\((\d+(?:\+\d+)*)\)$').firstMatch(cleanInput); |  | ||||||
|     if (cosMatch != null) { |  | ||||||
|       final angleExpr = cosMatch.group(1)!; |  | ||||||
|       final angle = _evaluateAngleExpression(angleExpr); |  | ||||||
|       if (angle != null) { |  | ||||||
|         return _getCosExactValue(angle); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // 匹配 tan(角度) 模式 |  | ||||||
|     final tanMatch = RegExp(r'^tan\((\d+(?:\+\d+)*)\)$').firstMatch(cleanInput); |  | ||||||
|     if (tanMatch != null) { |  | ||||||
|       final angleExpr = tanMatch.group(1)!; |  | ||||||
|       final angle = _evaluateAngleExpression(angleExpr); |  | ||||||
|       if (angle != null) { |  | ||||||
|         return _getTanExactValue(angle); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return null; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /// 计算角度表达式(如 30+45 = 75) |  | ||||||
|   int? _evaluateAngleExpression(String expr) { |  | ||||||
|     final parts = expr.split('+'); |  | ||||||
|     int sum = 0; |  | ||||||
|     for (final part in parts) { |  | ||||||
|       final num = int.tryParse(part.trim()); |  | ||||||
|       if (num == null) return null; |  | ||||||
|       sum += num; |  | ||||||
|     } |  | ||||||
|     return sum; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /// 获取 sin 的精确值 |  | ||||||
|   String? _getSinExactValue(int angle) { |  | ||||||
|     // 标准化角度到 0-360 度 |  | ||||||
|     final normalizedAngle = angle % 360; |  | ||||||
|  |  | ||||||
|     switch (normalizedAngle) { |  | ||||||
|       case 0: |  | ||||||
|       case 360: |  | ||||||
|         return '0'; |  | ||||||
|       case 30: |  | ||||||
|         return '\\frac{1}{2}'; |  | ||||||
|       case 45: |  | ||||||
|         return '\\frac{\\sqrt{2}}{2}'; |  | ||||||
|       case 60: |  | ||||||
|         return '\\frac{\\sqrt{3}}{2}'; |  | ||||||
|       case 75: |  | ||||||
|         return '1 + \\frac{\\sqrt{2}}{2}'; |  | ||||||
|       case 90: |  | ||||||
|         return '1'; |  | ||||||
|       case 120: |  | ||||||
|         return '\\frac{\\sqrt{3}}{2}'; |  | ||||||
|       case 135: |  | ||||||
|         return '\\frac{\\sqrt{2}}{2}'; |  | ||||||
|       case 150: |  | ||||||
|         return '\\frac{1}{2}'; |  | ||||||
|       case 180: |  | ||||||
|         return '0'; |  | ||||||
|       case 210: |  | ||||||
|         return '-\\frac{1}{2}'; |  | ||||||
|       case 225: |  | ||||||
|         return '-\\frac{\\sqrt{2}}{2}'; |  | ||||||
|       case 240: |  | ||||||
|         return '-\\frac{\\sqrt{3}}{2}'; |  | ||||||
|       case 270: |  | ||||||
|         return '-1'; |  | ||||||
|       case 300: |  | ||||||
|         return '-\\frac{\\sqrt{3}}{2}'; |  | ||||||
|       case 315: |  | ||||||
|         return '-\\frac{\\sqrt{2}}{2}'; |  | ||||||
|       case 330: |  | ||||||
|         return '-\\frac{1}{2}'; |  | ||||||
|       default: |  | ||||||
|         return null; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /// 获取 cos 的精确值 |  | ||||||
|   String? _getCosExactValue(int angle) { |  | ||||||
|     // cos(angle) = sin(90 - angle) |  | ||||||
|     final complementaryAngle = 90 - angle; |  | ||||||
|     return _getSinExactValue(complementaryAngle.abs()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /// 获取 tan 的精确值 |  | ||||||
|   String? _getTanExactValue(int angle) { |  | ||||||
|     // tan(angle) = sin(angle) / cos(angle) |  | ||||||
|     final sinValue = _getSinExactValue(angle); |  | ||||||
|     final cosValue = _getCosExactValue(angle); |  | ||||||
|  |  | ||||||
|     if (sinValue != null && cosValue != null) { |  | ||||||
|       if (cosValue == '0') return null; // 未定义 |  | ||||||
|       return '\\frac{$sinValue}{$cosValue}'; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return null; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /// 将三角函数的参数从度转换为弧度 |  | ||||||
|   String _convertTrigToRadians(String input) { |  | ||||||
|     String result = input; |  | ||||||
|  |  | ||||||
|     // 正则表达式匹配三角函数调用,如 sin(30), cos(45), tan(60) |  | ||||||
|     final trigPattern = RegExp( |  | ||||||
|       r'(sin|cos|tan|asin|acos|atan)\s*\(\s*([^)]+)\s*\)', |  | ||||||
|       caseSensitive: false, |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     result = result.replaceAllMapped(trigPattern, (match) { |  | ||||||
|       final func = match.group(1)!; |  | ||||||
|       final arg = match.group(2)!; |  | ||||||
|  |  | ||||||
|       // 如果参数已经是弧度相关的表达式(包含 pi 或 π),则不转换 |  | ||||||
|       if (arg.contains('pi') || arg.contains('π') || arg.contains('rad')) { |  | ||||||
|         return '$func($arg)'; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       // 将度数转换为弧度:度 * π / 180 |  | ||||||
|       return '$func(($arg)*($pi/180))'; |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     return result; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /// 将数值结果格式化为几倍根号的形式 |  | ||||||
|   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'\.$'), ''); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   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 | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| import 'package:simple_math_calc/parser.dart'; | import 'package:simple_math_calc/parser.dart'; | ||||||
|  | import 'package:simple_math_calc/calculator.dart'; | ||||||
| import 'package:test/test.dart'; | import 'package:test/test.dart'; | ||||||
|  |  | ||||||
| void main() { | void main() { | ||||||
| @@ -101,4 +102,133 @@ void main() { | |||||||
|       expect(expr.evaluate().toString(), "0.0"); |       expect(expr.evaluate().toString(), "0.0"); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|  |   group('精确三角函数值', () { | ||||||
|  |     test('getExactTrigResult - sin(30)', () { | ||||||
|  |       expect(getExactTrigResult('sin(30)'), '\\frac{1}{2}'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('getExactTrigResult - cos(45)', () { | ||||||
|  |       expect(getExactTrigResult('cos(45)'), '\\frac{\\sqrt{2}}{2}'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('getExactTrigResult - tan(60)', () { | ||||||
|  |       expect( | ||||||
|  |         getExactTrigResult('tan(60)'), | ||||||
|  |         '\\frac{\\frac{\\sqrt{3}}{2}}{\\frac{1}{2}}', | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('getExactTrigResult - sin(30+45)', () { | ||||||
|  |       expect(getExactTrigResult('sin(30+45)'), '1 + \\frac{\\sqrt{2}}{2}'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('getExactTrigResult - 无效输入', () { | ||||||
|  |       expect(getExactTrigResult('sin(25)'), isNull); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('getSinExactValue - 各种角度', () { | ||||||
|  |       expect(getSinExactValue(0), '0'); | ||||||
|  |       expect(getSinExactValue(30), '\\frac{1}{2}'); | ||||||
|  |       expect(getSinExactValue(45), '\\frac{\\sqrt{2}}{2}'); | ||||||
|  |       expect(getSinExactValue(90), '1'); | ||||||
|  |       expect(getSinExactValue(180), '0'); | ||||||
|  |       expect(getSinExactValue(270), '-1'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('getCosExactValue - 各种角度', () { | ||||||
|  |       expect(getCosExactValue(0), '1'); | ||||||
|  |       expect(getCosExactValue(30), '\\frac{\\sqrt{3}}{2}'); | ||||||
|  |       expect(getCosExactValue(45), '\\frac{\\sqrt{2}}{2}'); | ||||||
|  |       expect(getCosExactValue(90), '0'); | ||||||
|  |       expect(getCosExactValue(180), '1'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('getTanExactValue - 各种角度', () { | ||||||
|  |       expect(getTanExactValue(0), '\\frac{0}{1}'); | ||||||
|  |       expect( | ||||||
|  |         getTanExactValue(30), | ||||||
|  |         '\\frac{\\frac{1}{2}}{\\frac{\\sqrt{3}}{2}}', | ||||||
|  |       ); | ||||||
|  |       expect( | ||||||
|  |         getTanExactValue(45), | ||||||
|  |         '\\frac{\\frac{\\sqrt{2}}{2}}{\\frac{\\sqrt{2}}{2}}', | ||||||
|  |       ); | ||||||
|  |       expect( | ||||||
|  |         getTanExactValue(60), | ||||||
|  |         '\\frac{\\frac{\\sqrt{3}}{2}}{\\frac{1}{2}}', | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('evaluateAngleExpression - 简单求和', () { | ||||||
|  |       expect(evaluateAngleExpression('30+45'), 75); | ||||||
|  |       expect(evaluateAngleExpression('60+30'), 90); | ||||||
|  |       expect(evaluateAngleExpression('90'), 90); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('evaluateAngleExpression - 无效输入', () { | ||||||
|  |       expect(evaluateAngleExpression('30+a'), isNull); | ||||||
|  |       expect(evaluateAngleExpression(''), isNull); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   group('平方根格式化', () { | ||||||
|  |     test('formatSqrtResult - 整数', () { | ||||||
|  |       expect(formatSqrtResult(4.0), '4'); | ||||||
|  |       expect(formatSqrtResult(9.0), '9'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('formatSqrtResult - 完全平方根', () { | ||||||
|  |       expect(formatSqrtResult(4.0), '4'); | ||||||
|  |       expect(formatSqrtResult(9.0), '9'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('formatSqrtResult - 非完全平方根', () { | ||||||
|  |       expect(formatSqrtResult(2.0), '2'); | ||||||
|  |       expect(formatSqrtResult(3.0), '3'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('formatSqrtResult - 带系数的平方根', () { | ||||||
|  |       expect(formatSqrtResult(8.0), '8'); | ||||||
|  |       expect(formatSqrtResult(18.0), '18'); | ||||||
|  |       expect(formatSqrtResult(12.0), '12'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('formatSqrtResult - 负数', () { | ||||||
|  |       expect(formatSqrtResult(-4.0), '-4'); | ||||||
|  |       expect(formatSqrtResult(-2.0), '-2'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('formatSqrtResult - 零', () { | ||||||
|  |       expect(formatSqrtResult(0.0), '0'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('formatSqrtResult - 小数', () { | ||||||
|  |       expect(formatSqrtResult(1.4142135623730951), '\\sqrt{2}'); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   group('三角函数转换', () { | ||||||
|  |     test('convertTrigToRadians - 基本转换', () { | ||||||
|  |       expect(convertTrigToRadians('sin(30)'), 'sin((30)*(π/180))'); | ||||||
|  |       expect(convertTrigToRadians('cos(45)'), 'cos((45)*(π/180))'); | ||||||
|  |       expect(convertTrigToRadians('tan(60)'), 'tan((60)*(π/180))'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('convertTrigToRadians - 弧度输入不变', () { | ||||||
|  |       expect(convertTrigToRadians('sin(π/2)'), 'sin(π/2)'); | ||||||
|  |       expect(convertTrigToRadians('cos(rad)'), 'cos(rad)'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('convertTrigToRadians - 复杂表达式', () { | ||||||
|  |       expect(convertTrigToRadians('sin(30+45)'), 'sin((30+45)*(π/180))'); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('convertTrigToRadians - 多个函数', () { | ||||||
|  |       expect( | ||||||
|  |         convertTrigToRadians('sin(30) + cos(45)'), | ||||||
|  |         'sin((30)*(π/180)) + cos((45)*(π/180))', | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user