4

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

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 中工作,但任何语言的解决方案都可以。

编辑

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

我真的认为这可以在没有大量解析的情况下完成。但似乎某些解析器将遍历表达式并将其保存在表达式树中是不可避免的。

4

6 回答 6

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 ...

显然这有点伪代码,但它应该可以帮助您简化完整的语句

于 2009-06-30T12:54:08.610 回答
1

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

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

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

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

T1 = (([V].[6432])-([V].[6445]))*(((([V].[6443]))/1000*([V].[6448])+(([V].[6443]))*([V].[6449])+([V].[6450]))*(1-([V].[6446])))))
T2 = etc...
于 2009-06-30T12:53:34.587 回答
1

我知道这个线程真的很旧,但是可以从谷歌搜索到。

我正在编写一个解决类似问题的 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 的值,而 + 将给出 1 的值。结果数将为 4,这表明实际上需要括号。在 (2)^5 的情况下,内部值为 5,外部值为 5,最终值为 0,表明括号不重要,可以删除。

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

于 2011-04-04T13:53:30.257 回答
0

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

于 2009-06-30T12:35:59.210 回答
0

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

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

另外,为什么不能超过 255 个字符?如果您将其作为字符串字段存储在 Access 表中,则可以尝试将表达式的一半放在 1 个字段中,将另一半放在另一个字段中。

于 2009-06-30T12:37:43.840 回答
0

您还可以尝试使用 ANTLR、yacc 或类似工具解析您的表达式并创建解析树。这些树通常优化括号。然后你只需要从树创建表达式(显然没有括号)。

不过,您可能需要几个小时才能完成这项工作。但是表达式解析通常是泛型解析的第一个示例,因此您可能可以取样并根据需要对其进行修改。

于 2009-06-30T12:46:53.960 回答