您可以使用以下函数生成包含所有可能操作集的集合(例如 {-,-,-,-}, {-,-,-,+}, {-,-,+,-} 等)将输出一个布尔数组列表,其中 true 和 false 代表 + 和 -。该vars
参数表示要组合的变量的数量。请注意,对于 5 个变量,只有 16 个组合(不是您所说的 32 个),因为组合 5 个变量时只有 4 个运算符(假设第一个变量不能被否定):
public List<bool[]> GetOperators(int vars)
{
var result = new List<bool[]>();
for (var i = 0; i < 1 << vars-1; i++)
{
var item = new bool[vars - 1];
for (var j = 0; j < vars-1; j++)
{
item[j] = ((i >> j) & 1) != 0;
}
result.Add(item);
}
return result;
}
获得此列表后,您可以使用它以所有可能的方式组合变量。首先,我们定义一个辅助函数来获取一组变量和单个bool[]
组合并应用它(它假设组合中的元素数量对于传递的变量数量是正确的):
private double Combine(double[] vars, bool[] combination)
{
var sum = vars[0];
for (var i = 1; i< vars.Length; i++)
{
sum = combination[i - 1] ? sum + vars[i] : sum - vars[i];
}
return sum;
}
您还可以使用以下方法很好地格式化组合:
private string FormatCombination(double[] vars, bool[] combination)
{
var result = vars[0].ToString("0.00##");
for (var i = 1; i < vars.Length; i++)
{
result = string.Format("{0} {1} {2:0.00##}", result, combination[i - 1] ? "+" : "-", vars[i]);
}
return result;
}
将它们放在一起以测试所有可能的组合:
var vars = new []
{
1.23, // A
0.02, // B1
0.11, // B2
0.05, // C1
1.26 // C2
};
foreach (var combination in GetOperators(vars.Length))
{
var combined = Combine(vars, combination);
// Perform your operations on "combined" here...
Console.WriteLine("{0} = {1}", FormatCombination(vars, combination), combined);
}
这将输出:
1.23 - 0.02 - 0.11 - 0.05 - 1.26 = -0.21
1.23 + 0.02 - 0.11 - 0.05 - 1.26 = -0.17
1.23 - 0.02 + 0.11 - 0.05 - 1.26 = 0.01
1.23 + 0.02 + 0.11 - 0.05 - 1.26 = 0.05
1.23 - 0.02 - 0.11 + 0.05 - 1.26 = -0.11
1.23 + 0.02 - 0.11 + 0.05 - 1.26 = -0.07
1.23 - 0.02 + 0.11 + 0.05 - 1.26 = 0.11
1.23 + 0.02 + 0.11 + 0.05 - 1.26 = 0.15
1.23 - 0.02 - 0.11 - 0.05 + 1.26 = 2.31
1.23 + 0.02 - 0.11 - 0.05 + 1.26 = 2.35
1.23 - 0.02 + 0.11 - 0.05 + 1.26 = 2.53
1.23 + 0.02 + 0.11 - 0.05 + 1.26 = 2.57
1.23 - 0.02 - 0.11 + 0.05 + 1.26 = 2.41
1.23 + 0.02 - 0.11 + 0.05 + 1.26 = 2.45
1.23 - 0.02 + 0.11 + 0.05 + 1.26 = 2.63
1.23 + 0.02 + 0.11 + 0.05 + 1.26 = 2.67
编辑:
根据您对问题的更改,我已经更新了我的答案。正如其他人所提到的,可能没有必要使用这样的完整搜索,但无论如何您可能会发现该方法很有用。
GetOperators()
稍微改变以返回 2 n 个组合(而不是像以前那样的 2 n-1):
public List<bool[]> GetOperators(int vars)
{
var result = new List<bool[]>();
for (var i = 0; i < 1 << vars; i++)
{
var item = new bool[vars];
for (var j = 0; j < vars; j++)
{
item[j] = ((i >> j) & 1) != 0;
}
result.Add(item);
}
return result;
}
除了要使用的变量和组合之外,该Combine()
方法已更改为采用一组增量。对于组合的每个元素,如果是true
,则将增量添加到变量中,如果为假,则减去:
private double[] Combine(double[] vars, double[] increments, bool[] combination)
{
// Assuming here that vars, increments and combination all have the same number of elements
var result = new double[vars.Length];
for (var i = 0; i < vars.Length; i++)
{
result[i] = combination[i] ? vars[i] + increments[i] : vars[i] - increments[i];
}
// Returns an array of the vars and increments combined per the given combination
// E.g. if there are 5 vars and the combination is: {true, false, true, true, false}
// The result will be {var1 + inc1, var2 - inc2, var3 + inc3, var4 + inc4, var 5 - inc5}
return result;
}
并且FormatCombination()
还更新为显示新的组合样式:
private string FormatCombination(double[] vars, double[] increments, bool[] combination)
{
var result = new List<string>(vars.Length);
var combined = Combine(vars, increments, combination);
for (var i = 0; i < vars.Length; i++)
{
result.Add(string.Format("{0:0.00##} {1} {2:0.00##} = {3:0.00##}", vars[i], combination[i] ? "+" : "-", increments[i], combined[i]));
}
return string.Join(", ", result.ToArray());
}
把它们放在一起:
var vars = new[]
{
1.23, // A
0.02, // B
0.11, // C
0.05, // D
1.26, // E
};
var increments = new[]
{
0.04, // incA
0.11, // incB
0.01, // incC
0.37, // incD
0.85, // incD
};
foreach (var combination in GetOperators(vars.Length))
{
var combined = Combine(vars, increments, combination);
// Perform operation on combined here...
Console.WriteLine(FormatCombination(vars, increments, combination));
}
输出(删节):
1.23 - 0.04 = 1.19, 0.02 - 0.11 = -0.09, 0.11 - 0.01 = 0.10, 0.05 - 0.37 = -0.32, 1.26 - 0.85 = 0.41
1.23 + 0.04 = 1.27, 0.02 - 0.11 = -0.09, 0.11 - 0.01 = 0.10, 0.05 - 0.37 = -0.32, 1.26 - 0.85 = 0.41
1.23 - 0.04 = 1.19, 0.02 + 0.11 = 0.13, 0.11 - 0.01 = 0.10, 0.05 - 0.37 = -0.32, 1.26 - 0.85 = 0.41
1.23 + 0.04 = 1.27, 0.02 + 0.11 = 0.13, 0.11 - 0.01 = 0.10, 0.05 - 0.37 = -0.32, 1.26 - 0.85 = 0.41
...