如何摆脱数学表达式中不必要的括号

时间:2009-06-30 12:14:20

标签: algorithm math expression

嗨我想知道是否有任何已知方法可以摆脱数学公式中不必要的括号。我问这个问题的原因是我必须尽量减少这样的公式长度

if((-if(([V].[6432])=0;0;(([V].[6432])-([V].[6445]))*(((([V].[6443]))/1000*([V].[6448])
+(([V].[6443]))*([V].[6449])+([V].[6450]))*(1-([V].[6446])))))=0;([V].[6428])*
((((([V].[6443]))/1000*([V].[6445])*([V].[6448])+(([V].[6443]))*([V].[6445])*
([V].[6449])+([V].[6445])*([V].[6450])))*(1-([V].[6446])));

它基本上是sql select语句的一部分。它不能超过255个字符,我不能修改产生这个公式的代码(基本上是一个黑盒子;)) 如你所见,许多括号都没用。没有提到:

((a) * (b)) + (c) = a * b + c

所以我想保持操作的顺序为括号,乘法/除法,加/减。

我在VB工作,但任何语言的解决方案都没问题。

修改

我发现了一个相反的问题(在表达式中添加括号)Question

我真的认为这可以在不进行大量解析的情况下完成。但似乎一些将通过表达式并将其保存在表达式树中的解析器是不可避免的。

6 个答案:

答案 0 :(得分:2)

你可以删除最简单的案例:

([V].[6432]) and (([V].[6443]))

变为

v.[6432]

您不应该在表名或别名周围使用[]。

如果您可以为列添加别名,则可以进一步缩短它:

select v.[6432] as a, v.[6443] as b, ....

或者甚至将所有被查询的表放入一个子查询中 - 那么您就不需要表前缀:

if((-if(a=0;0;(a-b)*((c/1000*d
+c*e+f)*(1-g))))=0;h*
(((c/1000*b*d+c*b*
e+b*f))*(1-g));

select [V].[6432] as a, [V].[6445] as b, [V].[6443] as c, [V].[6448] as d, 
    [V].[6449] as e, [V].[6450] as f,[V].[6446] as g, [V].[6428] as h ...

显然这只是一些psedo-code,但它应该可以帮助你简化完整的陈述

答案 1 :(得分:1)

如果您有兴趣删除表达式中不必要的括号,则通用解决方案包括解析文本并构建关联的表达式树。

然后,通过应用一些规则,您可以从此树中找到没有必要括号的相应文本:

  • 如果节点是“+”,则不需要括号
  • 如果节点是“*”,则只有当左(右)孩子为“+”时,左(右)孩子才需要括号
  • 同样适用于“/”

但如果您的问题只是处理这255个字符,您可以只使用中间变量来存储中间结果

T1 = (([V].[6432])-([V].[6445]))*(((([V].[6443]))/1000*([V].[6448])+(([V].[6443]))*([V].[6449])+([V].[6450]))*(1-([V].[6446])))))
T2 = etc...

答案 2 :(得分:1)

我知道这个帖子确实很旧,但是可以从google搜索到。

我正在编写一个解决类似问题的TI-83 plus计算器程序。在我的情况下,我试图实际解决数字中特定变量的等式,但它可能仍然与您的问题有关,虽然我使用的是数组,因此我可能更容易选择特定的值。 ..
它还没有完成,但它确实摆脱了绝大多数的括号(我认为),这是一个有点优雅的解决方案。

我所做的是扫描等式/函数/无论如何,跟踪每个开始括号“(”直到我找到一个结束括号“)”,此时我可以放心,我不会碰到任何更深层次的嵌套括号。

y =((3x +(2)))首先显示(2),然后显示(3x +(2)),然后显示((3x + 2)))。

它的作用是检查每个括号前后的值。在上面的例子中,它将返回+和)。每个都分配了一个数字值。在他们两个之间,使用更高的。如果找不到运算符(*,/,+,^或 - ),则默认值为0。

接下来,我扫描括号内部。我使用类似的编号系统,虽然在这种情况下我使用的是找到的最低值,而不是最高值。如果没有找到任何内容,我默认值为5,如上例所示。

这个想法是你可以通过减去两个值来为括号的重要性分配一个数字。如果你在括号外面有类似^的东西 (2 + 3)^ 5 这些括号可能非常重要,并且会被赋予很高的价值,(在我的程序中,我使用5代表^)。

然而,内部运算符可能会使括号变得非常不重要, (2)^ 5 没有找到任何东西。在这种情况下,内部将被赋值为5.通过减去这两个值,您可以简单地通过检查结果数是否大于0来确定是否需要一组括号。在(2的情况下) + 3)^ 5,a ^将给出值5,而a +将给出值1.结果数字将为4,这表示实际上需要括号。 在(2)^ 5的情况下,您将得到内部值5和外部值5 最终值为0,表示括号不重要,可以删除。

这样做的缺点是,(至少在TI-83上)扫描这个等式很多次都是非常缓慢的。但如果速度不是问题...... 不知道这是否会有所帮助,我可能完全偏离主题。希望你能把一切都搞定。

答案 3 :(得分:0)

我很确定为了确定哪些括号是不必要的,你来评估它们中的表达式。因为你可以嵌套括号,所以这是一种递归问题,正则表达式只能以浅层方式处理,并且很可能是不正确的结果。如果您已经在评估表达式,可能您希望尽可能简化公式。这也有点棘手,在某些方法中使用了机器学习中也会出现的技术,例如您可能会在下面的文章中看到:http://portal.acm.org/citation.cfm?id=1005298

答案 4 :(得分:0)

如果您的变量名称从1个查询到下一个查询没有显着变化,您可以尝试一系列replace()命令。即。

X=replace([QryString],"(([V].[6443]))","[V].[6443]")

另外,为什么它不能超过255个字符?如果您将此字符串字段存储在Access表中,那么您可以尝试将一半表达式放在1个字段中,将后半部分放在另一个字段中。

答案 5 :(得分:0)

您也可以尝试使用ANTLR,yacc或类似方法解析表达式并创建一个解析树。这些树通常会优化括号。然后你只需要从树中创建表达式(显然没有括号)。

这可能需要花费几个小时来完成这项工作。但是表达式解析通常是泛型解析的第一个例子,因此您可以根据需要采样并修改它。