Percentage

This commit is contained in:
2025-09-14 14:13:14 +08:00
parent 6590c33732
commit 5cf66cd1f2
3 changed files with 147 additions and 1 deletions

View File

@@ -151,6 +151,17 @@ class AddExpr extends Expr {
return IntExpr(l.value + r.value);
}
// 小数相加
if (l is DoubleExpr && r is DoubleExpr) {
return DoubleExpr(l.value + r.value);
}
if (l is IntExpr && r is DoubleExpr) {
return DoubleExpr(l.value + r.value);
}
if (l is DoubleExpr && r is IntExpr) {
return DoubleExpr(l.value + r.value);
}
// 分数相加 / 分数与整数相加
if (l is FractionExpr && r is FractionExpr) {
return FractionExpr(
@@ -171,6 +182,14 @@ class AddExpr extends Expr {
).simplify();
}
// 分数与小数相加
if (l is FractionExpr && r is DoubleExpr) {
return DoubleExpr(l.numerator / l.denominator + r.value);
}
if (l is DoubleExpr && r is FractionExpr) {
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);
@@ -221,6 +240,18 @@ class SubExpr extends Expr {
if (l is IntExpr && r is IntExpr) {
return IntExpr(l.value - r.value);
}
// 小数相减
if (l is DoubleExpr && r is DoubleExpr) {
return DoubleExpr(l.value - r.value);
}
if (l is IntExpr && r is DoubleExpr) {
return DoubleExpr(l.value - r.value);
}
if (l is DoubleExpr && r is IntExpr) {
return DoubleExpr(l.value - r.value);
}
if (l is FractionExpr && r is FractionExpr) {
return FractionExpr(
l.numerator * r.denominator - r.numerator * l.denominator,
@@ -240,6 +271,14 @@ class SubExpr extends Expr {
).simplify();
}
// 分数与小数相减
if (l is FractionExpr && r is DoubleExpr) {
return DoubleExpr(l.numerator / l.denominator - r.value);
}
if (l is DoubleExpr && r is FractionExpr) {
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);
@@ -311,6 +350,18 @@ class MulExpr extends Expr {
if (l is IntExpr && r is IntExpr) {
return IntExpr(l.value * r.value);
}
// 小数相乘
if (l is DoubleExpr && r is DoubleExpr) {
return DoubleExpr(l.value * r.value);
}
if (l is IntExpr && r is DoubleExpr) {
return DoubleExpr(l.value * r.value);
}
if (l is DoubleExpr && r is IntExpr) {
return DoubleExpr(l.value * r.value);
}
if (l is FractionExpr && r is IntExpr) {
return FractionExpr(l.numerator * r.value, l.denominator).simplify();
}
@@ -324,6 +375,14 @@ class MulExpr extends Expr {
).simplify();
}
// 分数与小数相乘
if (l is FractionExpr && r is DoubleExpr) {
return DoubleExpr(l.numerator / l.denominator * r.value);
}
if (l is DoubleExpr && r is FractionExpr) {
return DoubleExpr(l.value * r.numerator / r.denominator);
}
// sqrt * sqrt: sqrt(a)*sqrt(a) = a
if (l is SqrtExpr &&
r is SqrtExpr &&
@@ -856,6 +915,37 @@ class AbsExpr extends Expr {
String toString() => "|$inner|";
}
// === PercentExpr ===
class PercentExpr extends Expr {
final Expr inner;
PercentExpr(this.inner);
@override
Expr simplify() => PercentExpr(inner.simplify());
@override
Expr evaluate() {
var i = inner.evaluate();
if (i is IntExpr) {
return DoubleExpr(i.value / 100.0);
}
if (i is DoubleExpr) {
return DoubleExpr(i.value / 100.0);
}
if (i is FractionExpr) {
return DoubleExpr(i.numerator / (i.denominator * 100.0));
}
return PercentExpr(i);
}
@override
Expr substitute(String varName, Expr value) =>
PercentExpr(inner.substitute(varName, value));
@override
String toString() => "$inner%";
}
// === 辅助:识别 a * sqrt(X) 形式 ===
class _SqrtTerm {
final int coef;

View File

@@ -17,7 +17,15 @@ class Parser {
}
}
Expr parse() => parseAdd();
Expr parse() {
var expr = parseAdd();
skipSpaces();
if (!isEnd && current == '%') {
eat();
expr = PercentExpr(expr);
}
return expr;
}
Expr parseAdd() {
var expr = parseMul();
@@ -46,6 +54,12 @@ class Parser {
}
skipSpaces();
}
// Handle percentage operator
skipSpaces();
if (!isEnd && current == '%') {
eat();
expr = PercentExpr(expr);
}
return expr;
}