如果你把自己限制在上面显示的那种线性函数,你可以像这样概括这个函数
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; // Initialization required because the compiler is not smart
// enough to infer that unknownIndex will be initialized when
// our code reaches the return statement.
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)。
如果你使用双打来表示幂,你甚至可以表示像这样的函数
5
7*x^3 + --- + 4*sqrt(z) = 11
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。上面显示的算法仅适用于未知数在方程中恰好出现一次的情况。