生成并执行所有可能的数学方程式

时间:2017-05-01 09:28:34

标签: c# math equation-solving

鉴于我有3个双打:

double a = 1.0;
double b = 2.0;
double c = 3.0;

如何使用以下操作生成所有可能的数学方程式:

  • +
  • *
  • ^2
  • sqrt()
  • 括号()

示例如下:

  • 1 + 2 + 3;
  • 1 + 2 * 3;
  • (1 + 2)* 3;
  • 1 ^ 2 * 2 * 3;
  • 1 *(2 ^ 2 + sqrt(3))
  • ...
总的来说,我的方法将是:

  • 生成每个等式的字符串

  • 使用本机roslyn编译器执行字符串,或创建自己的逻辑执行实现,或使用ncalc

    等解决方案

第一个选项是最好的,但它不是最快的。所以我的问题是 - 如何在example部分中生成字符串,或者如果有更好的方法解决这个问题 - 我想听听这些想法。

1 个答案:

答案 0 :(得分:1)

我在表达树和无上下文语法方面考虑这个问题。你可以说像

EXPRESSION ::=
    1 | 2 | 3
  | ( EXPRESSION )+( EXPRESSION )
  | ( EXPRESSION )*( EXPRESSION )
  | ( EXPRESSION )^2
  | sqrt( EXPRESSION )
  ;

这对括号有点过分了,所以如果你关心漂亮的字符串,你可能想要在后处理步骤中清理多余的parens,或者使用一些更精细的语法与多个非终端来正确处理它们。

您可以从三个终端规则的表达式树开始,即您的三个常量。然后,您可以考虑每个递归规则并插入您的常量来代替非终端。所以你生成1 + 1,1 + 2,1 + 3,2 + 1,2 + 2,2 + 3 + 3 + 1,3 + 2,3 + 3,(1)*(1) ,......像

这样的东西
for op in [plus, times]:
  for lhs in expressions:
    for rhs in expressions:
      new_expressions.append(binaryop(lhs, op, rhs))
for op in [square, sqrt]:
  for arg in expressions:
    new_expressions.append(unaryop(op, arg))

然后在每个这样的循环之后,你将不得不使用新发现的表达式来扩展表达式集。对于下一轮,您将尝试确保在最后一轮中生成至少一个操作数。对于二进制操作,另一个可能更旧。

如果每个可能的值只使用一个公式,事情就会变得更加可行。因此,一旦你发现1 + 3可以用作4的表达式,你就不会做2 + 2和2 * 2以及2 ^ 2,依此类推,因为表达4的一种方式就足够了。取决于申请。