More root available

This commit is contained in:
2025-09-16 18:56:16 +08:00
parent 656f29623b
commit dd4a9f524e
4 changed files with 389 additions and 49 deletions

View File

@@ -197,11 +197,17 @@ class AddExpr extends Expr {
return DoubleExpr(l.value + r.numerator / r.denominator);
}
// 合并同类的 sqrt 项: a*sqrt(X) + b*sqrt(X) = (a+b)*sqrt(X)
var a = _asSqrtTerm(l);
var b = _asSqrtTerm(r);
if (a != null && b != null && a.inner.toString() == b.inner.toString()) {
return MulExpr(IntExpr(a.coef + b.coef), SqrtExpr(a.inner)).simplify();
// 合并同类的项: a*root(X,n) + b*root(X,n) = (a+b)*root(X,n)
var a = _asRootTerm(l);
var b = _asRootTerm(r);
if (a != null &&
b != null &&
a.inner.toString() == b.inner.toString() &&
a.index == b.index) {
return MulExpr(
IntExpr(a.coef + b.coef),
SqrtExpr(a.inner, a.index),
).simplify();
}
return AddExpr(l, r);
@@ -286,11 +292,17 @@ class SubExpr extends Expr {
return DoubleExpr(l.value - r.numerator / r.denominator);
}
// 处理同类 sqrt 项: a*sqrt(X) - b*sqrt(X) = (a-b)*sqrt(X)
var a = _asSqrtTerm(l);
var b = _asSqrtTerm(r);
if (a != null && b != null && a.inner.toString() == b.inner.toString()) {
return MulExpr(IntExpr(a.coef - b.coef), SqrtExpr(a.inner)).simplify();
// 处理同类项: a*root(X,n) - b*root(X,n) = (a-b)*root(X,n)
var a = _asRootTerm(l);
var b = _asRootTerm(r);
if (a != null &&
b != null &&
a.inner.toString() == b.inner.toString() &&
a.index == b.index) {
return MulExpr(
IntExpr(a.coef - b.coef),
SqrtExpr(a.inner, a.index),
).simplify();
}
return SubExpr(l, r);
@@ -390,11 +402,9 @@ class MulExpr extends Expr {
return DoubleExpr(l.value * r.numerator / r.denominator);
}
// sqrt * sqrt: sqrt(a)*sqrt(a) = a
if (l is SqrtExpr &&
r is SqrtExpr &&
l.inner.toString() == r.inner.toString()) {
return l.inner.simplify();
// 根号相乘: root(a,n)*root(b,n) = root(a*b,n)
if (l is SqrtExpr && r is SqrtExpr && l.index == r.index) {
return SqrtExpr(MulExpr(l.inner, r.inner), l.index).simplify();
}
// int * sqrt -> 保留形式,之后 simplify() 再处理约分
@@ -523,28 +533,51 @@ class DivExpr extends Expr {
// === SqrtExpr.evaluate ===
class SqrtExpr extends Expr {
final Expr inner;
SqrtExpr(this.inner);
final int index; // 根的次数默认为2平方根
SqrtExpr(this.inner, [this.index = 2]);
@override
Expr simplify() {
var i = inner.simplify();
if (i is IntExpr) {
int n = i.value;
int root = sqrt(n).floor();
if (root * root == n) {
return IntExpr(root); // 完全平方数
}
// 尝试拆分 sqrt比如 sqrt(8) = 2*sqrt(2)
for (int k = root; k > 1; k--) {
if (n % (k * k) == 0) {
return MulExpr(
IntExpr(k),
SqrtExpr(IntExpr(n ~/ (k * k))),
).simplify();
if (index == 2) {
// 平方根的特殊处理
int root = sqrt(n).floor();
if (root * root == n) {
return IntExpr(root); // 完全平方数
}
// 尝试拆分 sqrt比如 sqrt(8) = 2*sqrt(2)
for (int k = root; k > 1; k--) {
if (n % (k * k) == 0) {
return MulExpr(
IntExpr(k),
SqrtExpr(IntExpr(n ~/ (k * k))),
).simplify();
}
}
} else {
// 任意次根的处理
// 检查是否为完全 n 次幂
if (n >= 0) {
int root = (pow(n, 1.0 / index)).round();
if ((pow(root, index) - n).abs() < 1e-10) {
return IntExpr(root); // 完全 n 次幂
}
// 尝试提取系数比如对于立方根27^(1/3) = 3
for (int k = root; k > 1; k--) {
int power = (pow(k, index)).round();
if (n % power == 0) {
return MulExpr(
IntExpr(k),
SqrtExpr(IntExpr(n ~/ power), index),
).simplify();
}
}
}
}
}
return SqrtExpr(i);
return SqrtExpr(i, index);
}
@override
@@ -552,27 +585,50 @@ class SqrtExpr extends Expr {
var i = inner.evaluate();
if (i is IntExpr) {
int n = i.value;
int root = sqrt(n).floor();
if (root * root == n) return IntExpr(root);
// 拆平方因子并返回 k * sqrt(remain)
for (int k = root; k > 1; k--) {
if (n % (k * k) == 0) {
return MulExpr(
IntExpr(k),
SqrtExpr(IntExpr(n ~/ (k * k))),
).evaluate();
if (index == 2) {
// 平方根的特殊处理
int root = sqrt(n).floor();
if (root * root == n) return IntExpr(root);
// 拆平方因子并返回 k * sqrt(remain)
for (int k = root; k > 1; k--) {
if (n % (k * k) == 0) {
return MulExpr(
IntExpr(k),
SqrtExpr(IntExpr(n ~/ (k * k))),
).evaluate();
}
}
} else {
// 任意次根的数值计算
if (n >= 0) {
double result = pow(n.toDouble(), 1.0 / index).toDouble();
return DoubleExpr(result);
}
}
}
return SqrtExpr(i);
if (i is DoubleExpr) {
double result = pow(i.value, 1.0 / index).toDouble();
return DoubleExpr(result);
}
if (i is FractionExpr) {
double result = pow(i.numerator / i.denominator, 1.0 / index).toDouble();
return DoubleExpr(result);
}
return SqrtExpr(i, index);
}
@override
Expr substitute(String varName, Expr value) =>
SqrtExpr(inner.substitute(varName, value));
SqrtExpr(inner.substitute(varName, value), index);
@override
String toString() => "\\sqrt{${inner.toString()}}";
String toString() {
if (index == 2) {
return "\\sqrt{${inner.toString()}}";
} else {
return "\\sqrt[$index]{${inner.toString()}}";
}
}
}
// === CosExpr ===
@@ -970,22 +1026,31 @@ class PercentExpr extends Expr {
String toString() => "$inner%";
}
// === 辅助:识别 a * sqrt(X) 形式 ===
class _SqrtTerm {
// 扩展 _SqrtTerm 以支持任意次根
class _RootTerm {
final int coef;
final Expr inner;
_SqrtTerm(this.coef, this.inner);
final int index;
_RootTerm(this.coef, this.inner, this.index);
}
_SqrtTerm? _asSqrtTerm(Expr e) {
if (e is SqrtExpr) return _SqrtTerm(1, e.inner);
_RootTerm? _asRootTerm(Expr e) {
if (e is SqrtExpr) return _RootTerm(1, e.inner, e.index);
if (e is MulExpr) {
// 可能为 Int * Sqrt or Sqrt * Int
if (e.left is IntExpr && e.right is SqrtExpr) {
return _SqrtTerm((e.left as IntExpr).value, (e.right as SqrtExpr).inner);
return _RootTerm(
(e.left as IntExpr).value,
(e.right as SqrtExpr).inner,
(e.right as SqrtExpr).index,
);
}
if (e.right is IntExpr && e.left is SqrtExpr) {
return _SqrtTerm((e.right as IntExpr).value, (e.left as SqrtExpr).inner);
return _RootTerm(
(e.right as IntExpr).value,
(e.left as SqrtExpr).inner,
(e.left as SqrtExpr).index,
);
}
}
return null;