/* 此文件实现了有理数与二次根式形成的数域 * 需要在pubspec.yaml中添加依赖rational: ^2.2.3 * 使用方法请看最后的测试用例 * Ksqrt类表示有理数乘以根号整数 * RationalExtend类表示多个Ksqrt类根式相加 * Author:nonvioce * Time: 2025.10.26 */ import 'package:rational/rational.dart'; import 'dart:math'; class Ksqrt { Rational k; // 有理数系数 int q; // 底数(整数) Ksqrt(this.k, this.q) { if (q < 0) throw ArgumentError("底数q不能为负数"); } // 从整数创建(系数为整数,底数为1) factory Ksqrt.fromInt(int value) { return Ksqrt(Rational.fromInt(value), 1); } // 从Rational创建(系数为有理数,底数为1) factory Ksqrt.fromRational(Rational rational) { return Ksqrt(rational, 1); } // 增强的字符串解析 - 增加小数支持 factory Ksqrt.parse(String str) { str = str.trim(); // 处理纯数字(整数或小数) if (RegExp(r'^-?\d+(\.\d+)?$').hasMatch(str)) { return Ksqrt.fromRational(_parseRational(str)); } // 处理分数(不包含根号) if (str.contains('/') && !str.contains('√')) { try { var parts = str.split('/'); if (parts.length != 2) throw FormatException("无效的分数格式: $str"); var numerator = _parseRational(parts[0]); var denominator = _parseRational(parts[1]); if (denominator == Rational.zero) throw FormatException("分母不能为零: $str"); return Ksqrt.fromRational(numerator / denominator); } catch (e) { throw FormatException("无效的分数格式: $str, 错误: $e"); } } // 处理根式 if (str.contains('√')) { var sqrtIndex = str.indexOf('√'); var coefficientStr = str.substring(0, sqrtIndex); var radicandStr = str.substring(sqrtIndex + 1); // 处理括号内的底数 if (radicandStr.startsWith('(') && radicandStr.endsWith(')')) { radicandStr = radicandStr.substring(1, radicandStr.length - 1); } Rational k; // 解析系数 if (coefficientStr.isEmpty || coefficientStr == "+") { k = Rational.one; } else if (coefficientStr == "-") { k = -Rational.one; } else { coefficientStr = coefficientStr.replaceAll('*', ''); try { if (coefficientStr.contains('/')) { var coeffParts = coefficientStr.split('/'); if (coeffParts.length != 2) throw FormatException("无效的系数格式: $coefficientStr"); var num = _parseRational(coeffParts[0]); var den = _parseRational(coeffParts[1]); if (den == Rational.zero) throw FormatException("分母不能为零: $coefficientStr"); k = num / den; } else { k = _parseRational(coefficientStr); } } catch (e) { throw FormatException("无效的系数格式: $coefficientStr"); } } // 解析底数 int q; if (radicandStr.contains('/')) { throw FormatException("分数底数暂不支持: $str"); } else { try { // 底数必须是整数,所以使用int.parse而不是_parseRational q = int.parse(radicandStr); } catch (e) { throw FormatException("无效的底数格式: $radicandStr"); } } return Ksqrt(k, q)..simplify(); } // 尝试解析为有理数(包括小数) try { return Ksqrt.fromRational(_parseRational(str)); } catch (e) { throw FormatException("无法解析的字符串: $str"); } } // 小数转有理数的辅助函数 static Rational _parseRational(String input) { try { input = input.trim(); if (input.contains('/')) { List parts = input.split('/'); if (parts.length == 2) { String numerator = parts[0].trim(); String denominator = parts[1].trim(); // 修复:直接使用 Rational 构造函数而不是 parse BigInt num = BigInt.parse(numerator); BigInt den = BigInt.parse(denominator); if (den == BigInt.zero) { throw FormatException('分母不能为零'); } return Rational(num, den); } } // 处理小数 if (input.contains('.')) { return _decimalToRational(input); } // 处理整数 return Rational.parse(input); } catch (e) { throw FormatException('无效的分数格式: $input'); } } // 小数转有理数的实现 static Rational _decimalToRational(String decimalStr) { if (!decimalStr.contains('.')) { return Rational.parse(decimalStr); } List parts = decimalStr.split('.'); String integerPart = parts[0]; String decimalPart = parts[1]; // 处理负号 bool isNegative = integerPart.startsWith('-'); if (isNegative) { integerPart = integerPart.substring(1); } // 如果整数部分是空的,设为0 if (integerPart.isEmpty) { integerPart = '0'; } // 计算分母:10的decimalPart长度次方 BigInt denominator = BigInt.from(10).pow(decimalPart.length); // 计算分子:整数部分 * 分母 + 小数部分 BigInt numerator = BigInt.parse(integerPart) * denominator + BigInt.parse(decimalPart); if (isNegative) { numerator = -numerator; } return Rational(numerator, denominator); } // 取反运算 Ksqrt operator -() { return Ksqrt(-k, q); } // 修复的化简方法 void simplify() { if (k == Rational.zero) { q = 1; return; } if (q == 0 || q == 1) return; // 提取平方因子 int squareFactor = 1; int temp = q; for (int i = 2; i * i <= temp; i++) { while (temp % (i * i) == 0) { squareFactor *= i; temp ~/= (i * i); } } // 更新系数和底数 if (squareFactor > 1) { k *= Rational.fromInt(squareFactor); q = temp; } } // 判断两个Ksqrt是否同类项 bool isLikeTerm(Ksqrt other) { Ksqrt thisCopy = Ksqrt(k, q); Ksqrt otherCopy = Ksqrt(other.k, other.q); thisCopy.simplify(); otherCopy.simplify(); return thisCopy.q == otherCopy.q; } // 加法运算 Ksqrt operator +(Ksqrt other) { if (!isLikeTerm(other)) { throw ArgumentError("底数不同无法相加: ${this.q} 和 ${other.q}"); } Ksqrt thisCopy = Ksqrt(k, q); Ksqrt otherCopy = Ksqrt(other.k, other.q); thisCopy.simplify(); otherCopy.simplify(); return Ksqrt(thisCopy.k + otherCopy.k, thisCopy.q); } // 减法运算 Ksqrt operator -(Ksqrt other) { if (!isLikeTerm(other)) { throw ArgumentError("底数不同无法相减: ${this.q} 和 ${other.q}"); } Ksqrt thisCopy = Ksqrt(k, q); Ksqrt otherCopy = Ksqrt(other.k, other.q); thisCopy.simplify(); otherCopy.simplify(); return Ksqrt(thisCopy.k - otherCopy.k, thisCopy.q); } // 乘法运算 Ksqrt operator *(Ksqrt other) { Rational newK = k * other.k; int newQ = q * other.q; Ksqrt result = Ksqrt(newK, newQ); result.simplify(); return result; } // 修复的除法运算 Ksqrt operator /(Ksqrt other) { if (other.k == Rational.zero) { throw ArgumentError("除数不能为零"); } // 分子分母同乘以分母的根号部分进行有理化 Rational newK = k * other.k; int newQ = q * other.q; // 除以分母系数的平方(因为分母是k√q,有理化后分母变为k²q) Rational denominator = other.k * other.k * Rational.fromInt(other.q); Ksqrt result = Ksqrt(newK / denominator, newQ); result.simplify(); return result; } @override bool operator ==(Object other) { if (identical(this, other)) return true; if (other is! Ksqrt) return false; Ksqrt thisSimplified = Ksqrt(k, q)..simplify(); Ksqrt otherSimplified = Ksqrt(other.k, other.q)..simplify(); return thisSimplified.k == otherSimplified.k && thisSimplified.q == otherSimplified.q; } @override int get hashCode { Ksqrt simplified = Ksqrt(k, q)..simplify(); return Object.hash(simplified.k, simplified.q); } // 计算表达式的近似浮点数值 double toDouble() { if (k == Rational.zero) return 0.0; double sqrtQ = sqrt(q.toDouble()); double kValue = k.toDouble(); return kValue * sqrtQ; } @override String toString() { if (k == Rational.zero) return '0'; if (q == 1) return k.toString(); String kStr; if (k == Rational.one) { kStr = ''; } else if (k == -Rational.one) { kStr = '-'; } else { if (k.isInteger) { kStr = k.toDouble().toInt().toString(); } else { kStr = '($k)'; } kStr += '*'; } return '${kStr}√$q'; } } class RationalExtend { List terms; RationalExtend(this.terms); factory RationalExtend.fromInt(int value) { return RationalExtend([Ksqrt.fromInt(value)]); } factory RationalExtend.fromRational(Rational rational) { return RationalExtend([Ksqrt.fromRational(rational)]); } // 改进的字符串解析 - 现在支持小数 factory RationalExtend.parse(String str) { str = str.replaceAll(' ', ''); if (str.isEmpty) return RationalExtend([]); // 处理单个项的情况 if (!str.contains('+') && !str.contains('-')) { return RationalExtend([Ksqrt.parse(str)]); } // 处理以负号开头的情况 if (str.startsWith('-')) { var rest = str.substring(1); if (!rest.contains('+') && !rest.contains('-')) { return RationalExtend([Ksqrt.parse(str)]); } } List terms = []; List termStrs = []; // 改进的分割逻辑:正确处理符号 int start = 0; for (int i = 1; i < str.length; i++) { if ((str[i] == '+' || str[i] == '-') && str[i-1] != '*' && str[i-1] != '/' && str[i-1] != '^') { termStrs.add(str.substring(start, i)); start = i; } } termStrs.add(str.substring(start)); // 解析各项 for (var termStr in termStrs) { if (termStr.isEmpty) continue; if (termStr == '+') continue; try { terms.add(Ksqrt.parse(termStr)); } catch (e) { throw FormatException("无法解析项: $termStr, 错误: $e"); } } return RationalExtend(terms)..simplify(); } void addTerm(Ksqrt term) { terms.add(term); } // 化简方法:合并同类项 void simplify() { if (terms.isEmpty) return; // 首先对每个项进行化简 for (var term in terms) { term.simplify(); } // 合并同类项 Map termMap = {}; for (var term in terms) { if (termMap.containsKey(term.q)) { termMap[term.q] = termMap[term.q]! + term.k; } else { termMap[term.q] = term.k; } } // 重建terms列表 terms.clear(); termMap.forEach((q, k) { if (k != Rational.zero) { terms.add(Ksqrt(k, q)); } }); // 按底数排序 terms.sort((a, b) => a.q.compareTo(b.q)); if (terms.isEmpty) { terms.add(Ksqrt.fromInt(0)); } } // 获取共轭表达式 RationalExtend get conjugate { if (terms.length == 1) { return RationalExtend([terms[0]]); } else if (terms.length == 2) { return RationalExtend([ terms[0], Ksqrt(-terms[1].k, terms[1].q) ]); } else { List conjugateTerms = [terms[0]]; for (int i = 1; i < terms.length; i++) { conjugateTerms.add(Ksqrt(-terms[i].k, terms[i].q)); } return RationalExtend(conjugateTerms); } } // 检查是否是有理数 bool get isRational { for (var term in terms) { if (term.q != 1) return false; } return true; } // 获取有理数部分的值 Rational get rationalValue { if (!isRational) { throw StateError("表达式包含根号,不是纯有理数"); } Rational sum = Rational.zero; for (var term in terms) { sum += term.k; } return sum; } // 加法运算 RationalExtend operator +(RationalExtend other) { List newTerms = List.from(terms); newTerms.addAll(other.terms); RationalExtend result = RationalExtend(newTerms); result.simplify(); return result; } // 减法运算 RationalExtend operator -(RationalExtend other) { List newTerms = List.from(terms); for (var term in other.terms) { newTerms.add(Ksqrt(-term.k, term.q)); } RationalExtend result = RationalExtend(newTerms); result.simplify(); return result; } // 乘法运算 RationalExtend operator *(RationalExtend other) { List productTerms = []; for (var term1 in terms) { for (var term2 in other.terms) { productTerms.add(term1 * term2); } } RationalExtend result = RationalExtend(productTerms); result.simplify(); return result; } // 修复的除法运算 RationalExtend operator /(RationalExtend other) { if (other.terms.isEmpty) { throw ArgumentError("除数不能为空"); } // 特殊情况:除数是单项式 if (other.terms.length == 1) { List newTerms = []; for (var term in terms) { newTerms.add(term / other.terms[0]); } return RationalExtend(newTerms)..simplify(); } // 一般情况:使用分母有理化 RationalExtend conjugate = other.conjugate; RationalExtend numerator = this * conjugate; RationalExtend denominator = other * conjugate; if (!denominator.isRational) { throw StateError("分母有理化失败,结果仍包含根号"); } Rational denomValue = denominator.rationalValue; if (denomValue == Rational.zero) { throw ArgumentError("分母有理化后为0,无法进行除法"); } // 将分子中的每一项除以分母的有理数值 List resultTerms = []; for (var term in numerator.terms) { resultTerms.add(Ksqrt(term.k / denomValue, term.q)); } return RationalExtend(resultTerms)..simplify(); } @override bool operator ==(Object other) { if (identical(this, other)) return true; if (other is! RationalExtend) return false; RationalExtend thisSimplified = RationalExtend(List.from(terms))..simplify(); RationalExtend otherSimplified = RationalExtend(List.from(other.terms))..simplify(); if (thisSimplified.terms.length != otherSimplified.terms.length) return false; for (int i = 0; i < thisSimplified.terms.length; i++) { if (thisSimplified.terms[i] != otherSimplified.terms[i]) { return false; } } return true; } @override int get hashCode { RationalExtend simplified = RationalExtend(List.from(terms))..simplify(); return simplified.terms.fold(0, (hash, term) => hash ^ term.hashCode); } // 计算表达式的近似浮点数值 double toDouble() { double sum = 0.0; for (var term in terms) { sum += term.toDouble(); } return sum; } @override String toString() { if (terms.isEmpty) return "0"; RationalExtend simplified = RationalExtend(List.from(terms))..simplify(); if (simplified.terms.isEmpty) return "0"; List termStrings = []; for (var term in simplified.terms) { String termStr = term.toString(); if (termStr.startsWith('-')) { termStrings.add(termStr); } else if (termStrings.isNotEmpty) { termStrings.add('+$termStr'); } else { termStrings.add(termStr); } } String result = termStrings.join(''); if (result.startsWith('+')) { result = result.substring(1); } return result; } } extension RationalExtendMath on RationalExtend { RationalExtend square() { return this * this; } RationalExtend abs() { double value = this.toDouble(); if (value < 0) { return RationalExtend(terms.map((term) => Ksqrt(-term.k, term.q)).toList()); } return this; } bool get isZero { RationalExtend simplified = RationalExtend(List.from(terms))..simplify(); return simplified.terms.length == 1 && simplified.terms[0].k == Rational.zero; } Rational get rationalPart { Rational sum = Rational.zero; for (var term in terms) { if (term.q == 1) { sum += term.k; } } return sum; } RationalExtend get irrationalPart { List irrationalTerms = []; for (var term in terms) { if (term.q != 1) { irrationalTerms.add(term); } } return RationalExtend(irrationalTerms)..simplify(); } } /*测试用例 // 测试函数 - 增加小数测试 void main() { print('=== Ksqrt 类测试 ==='); // 基本创建和化简 var sqrt8 = Ksqrt(Rational.one, 8); sqrt8.simplify(); print('√8 = $sqrt8'); // 应该输出 2√2 // 算术运算 var a = Ksqrt.parse('√2'); var b = Ksqrt.parse('3√2'); var sum = a + b; print('√2 + 3√2 = $sum'); // 应该输出 4√2 var product = a * b; print('√2 * 3√2 = $product'); // 应该输出 6 // 除法测试 - 修复后 var c = Ksqrt.parse('√6'); var d = Ksqrt.parse('√3'); var quotient = c / d; print('√6 / √3 = $quotient'); // 应该输出 √2 print('\n=== RationalExtend 类测试 ==='); // 多项式创建和运算 var expr1 = RationalExtend.parse('√2 + 2√3'); var expr2 = RationalExtend.parse('√2 - √3'); print('表达式1: $expr1'); print('表达式2: $expr2'); var polySum = expr1 + expr2; print('相加: $polySum'); // 应该输出 2√2 + √3 var polyProduct = expr1 * expr2; print('相乘: $polyProduct'); // 应该输出 2 + √6 - 2√3 - 2*3 = -4 + √6 - 2√3 // 除法测试(分母有理化)- 修复后 try { var polyQuotient = expr1 / expr2; print('相除: $polyQuotient'); // 应该输出有理化后的结果 } catch (e) { print('除法错误: $e'); } // 复杂表达式测试 print('\n=== 复杂表达式测试 ==='); try { var complexExpr = RationalExtend.parse('2/3'); print('分数解析: $complexExpr'); var complexExpr2 = RationalExtend.parse('2/3+√2'); print('分数+根号解析: $complexExpr2'); var complexExpr3 = RationalExtend.parse('1+√2'); var mul = complexExpr2 * complexExpr3; print('复杂表达式1: $complexExpr2'); print('复杂表达式2: $complexExpr3'); print('乘积: $mul'); print('有理数部分: ${complexExpr2.rationalPart}'); print('无理数部分: ${complexExpr2.irrationalPart}'); print('近似值: ${complexExpr2.toDouble()}'); } catch (e) { print('解析错误: $e'); } // 更多测试 print('\n=== 更多测试 ==='); try { var test1 = Ksqrt.parse('1/2'); print('分数 1/2: $test1'); var test2 = Ksqrt.parse('3/4*√2'); print('分数系数 3/4*√2: $test2'); var test3 = RationalExtend.parse('1/2 + 1/3*√2'); print('混合表达式: $test3'); } catch (e) { print('测试错误: $e'); } // 小数测试 print('\n=== 小数支持测试 ==='); try { var decimal1 = Ksqrt.parse('0.5'); print('小数 0.5: $decimal1'); var decimal2 = Ksqrt.parse('0.25√2'); print('小数系数 0.25√2: $decimal2'); var decimal3 = Ksqrt.parse('1.5√3'); print('小数系数 1.5√3: $decimal3'); var decimal4 = RationalExtend.parse('0.5 + 3/2√2'); print('混合小数表达式: $decimal4'); var decimal5 = RationalExtend.parse('1/3 + 0.666√2'); print('混合小数表达式: $decimal5'); // 小数运算测试 var decimalExpr1 = RationalExtend.parse('0.5√2'); var decimalExpr2 = RationalExtend.parse('0.25√2'); var decimalSum = decimalExpr1 + decimalExpr2; print('0.5√2 + 0.25√2 = $decimalSum'); // 应该输出 0.75√2 var decimalProduct = decimalExpr1 * decimalExpr2; print('0.5√2 * 0.25√2 = $decimalProduct'); // 应该输出 0.25 } catch (e) { print('小数测试错误: $e'); } } */