如果你限制自己只使用上面展示的线性函数,你可以像这样推广该函数。
3x - 5y + z = 5
将会变成
a[0]*x[0] + a[1]*x[1] + a[2]*x[2] = c
使用 a = { 3, -5, 1 }
和 c = 5
。
即,您需要一个常数因子列表(或数组)List<double> a;
和一个变量列表 List<double?> x;
,以及右侧的常数 double c;
public double Solve(IList<double> a, IList<double?> x, double c)
{
int unknowns = 0;
int unkonwnIndex = 0;
double sum = 0.0;
if (a.Count != x.Count) {
throw new ArgumentException("a[] and x[] must have same length");
}
for (int i = 0; i < a.Count; i++) {
if (x[i].HasValue) {
sum += a[i] * x[i].Value;
} else {
unknowns++;
unknownIndex = i;
}
}
if (unknowns != 1) {
throw new ArgumentException("Exactly one unknown expected");
}
return (c - sum) / a[unknownIndex];
}
例子:
3x - 5y + z = 5
5 - (- 5y + z)
x =
3
从这个例子中可以看出,解决方案包括从常数中减去除未知项以外的所有项的总和,然后除以未知项的系数。因此,我的解决方案记住了未知项的索引。
您可以像这样使用幂进行泛化,假设您有方程
a[0]*x[0]^p[0] + a[1]*x[1]^p[1] + a[2]*x[2]^p[2] = c
你需要添加一个额外的参数 IList<int> p
,结果会变成
return Math.Pow((c - sum) / a[unknownIndex], 1.0 / p[unknownIndex]);
当使用 x ^ (1/n)
时,它等同于 nth-root(x)
。
如果您对指数使用 doubles,则甚至可以表示像
5
7*x^3 +
y^2
a = { 7, 5, 4 }, p = { 3, -2, 0.5 }, c = 11
因为
1
x^(-n) = ---
x^n
并且
nth-root(x) = x^(1/n)
然而,您将无法找到真正的非线性多项式的根,例如x^2 - 5x = 7
。上面展示的算法仅在未知数在方程中出现一次时才有效。
IList<T>
,因此我将参数更改为IList<T>
。 - Olivier Jacot-Descombesif
和接下来的return
语句不应该在for
循环内部。 - Nikon the Third