生成并执行所有可能的数学方程式
generating and executing all possible math equations
假设我有 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
[ 等解决方案=49=]
第一个选项是最好的,但不是最快的。所以我的问题是 - 我如何像 example
部分那样生成字符串,或者是否有更好的方法来解决这个问题 - 我想听听这些想法。
我会从表达式树和上下文无关语法的角度考虑这个问题。你可以这样说
EXPRESSION ::=
1 | 2 | 3
| ( EXPRESSION )+( EXPRESSION )
| ( EXPRESSION )*( EXPRESSION )
| ( EXPRESSION )^2
| sqrt( EXPRESSION )
;
这对括号有点过分渴望,所以如果你关心漂亮的字符串,你可能想在后处理步骤中清理多余的括号,或者使用一些更复杂的带有多个非终结符的语法来处理这些正确。
您可以从三个终端规则的表达式树开始,即您的三个常量。然后你可以考虑每个递归规则并插入你拥有的常量来代替非终端。所以你会生成 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 的一种方式就足够了。取决于应用程序。
假设我有 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))
- ...
总的来说,我的方法如下:
生成每个方程的字符串
使用本机
[ 等解决方案=49=]roslyn
编译器执行字符串,或创建我自己的逻辑执行实现,或使用ncalc
第一个选项是最好的,但不是最快的。所以我的问题是 - 我如何像 example
部分那样生成字符串,或者是否有更好的方法来解决这个问题 - 我想听听这些想法。
我会从表达式树和上下文无关语法的角度考虑这个问题。你可以这样说
EXPRESSION ::=
1 | 2 | 3
| ( EXPRESSION )+( EXPRESSION )
| ( EXPRESSION )*( EXPRESSION )
| ( EXPRESSION )^2
| sqrt( EXPRESSION )
;
这对括号有点过分渴望,所以如果你关心漂亮的字符串,你可能想在后处理步骤中清理多余的括号,或者使用一些更复杂的带有多个非终结符的语法来处理这些正确。
您可以从三个终端规则的表达式树开始,即您的三个常量。然后你可以考虑每个递归规则并插入你拥有的常量来代替非终端。所以你会生成 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 的一种方式就足够了。取决于应用程序。