我正在开发一个用户可以为某些任务添加条件的应用程序。
例如,他可以有条件a,b,c,d并以最终看起来像这样的方式组合它们:
(a AND b) OR ( c AND d )
OR
(a AND b AND c) or d
OR
(a AND !b) AND c OR !d
等
如何通过删除括号将这些条件转换为等效条件?
答案 0 :(得分:3)
您可以使用各种properties布尔代数来帮助简化表达式,但您可能无法摆脱所有括号。括号是某些表达式所必需的,因为NOT,AND和OR没有操作顺序。因此,如果您无法重新排列表达式以从左向右阅读,则需要使用括号。
答案 1 :(得分:2)
布尔代数中的每个表达式都可以转换为等效表达式,不带括号,仅使用AND
,OR
和!
(一元NOT
)。
这是一个简单但效率低下的算法:
使用示例表达式(a OR !b) AND c
,
为变量的每个真值组合构建一个真值表:
| a | b | c | (a OR !b) AND c |
| 0 0 0 | 0 |
| 0 0 1 | 1 |
| 0 1 0 | 0 |
| 0 1 1 | 0 |
| 1 0 0 | 0 |
| 1 0 1 | 1 |
| 1 1 0 | 0 |
| 1 1 1 | 1 |
对于表达式为true的每组值(最右边的列中包含1
的每一行),使用AND
和!
创建一个表达式,其值为仅适用于该特定值集合。
| a | b | c | (a OR !b) AND c |
| 0 0 0 | 0 |
| 0 0 1 | 1 | (!a AND !b AND c )
| 0 1 0 | 0 |
| 0 1 1 | 0 |
| 1 0 0 | 0 |
| 1 0 1 | 1 | (a AND !b AND c )
| 1 1 0 | 0 |
| 1 1 1 | 1 | (a AND b AND c )
使用OR加入表达式。
(!a AND !b AND c ) OR (a AND !b AND c ) OR (a AND b AND c )
结果表达式很少是最小的,因此您可能希望在之后应用一些最小化技术。
(!a AND !b AND c) OR (a AND !b AND c) OR (a AND b AND c)
=
(!a AND !b AND c) OR (a AND c)
=
(!b AND c) OR (a AND c)
钽哒!
重要的是要注意,在步骤1中构建真值表是一个O(2 ^ n)操作(在变量的数量上),这很糟糕。对于具有大量变量的情况,您可能希望使用不同的技术。这个算法的主要优点是它可以很明显地将ANY表达式转换成你想要的形式。
编辑:要清楚,如果您使用的是普通优先规则,则可以删除最终表达式中的括号。
答案 2 :(得分:0)
不完全确定转换为非括号等价物的动机是什么,所以我认为你是在尝试为用户建立表达能力(即表达语言),以便将他们想要的任务条件传达给你的应用。
您不能删除对括号的需要,并且仍然支持具有正常运算符优先级规则的普通中缀表达式语言中的任意复杂表达式。
我认为你有几个选择:
支持括号。 (他们真的难以解析。)
使用不使用括号的备用相对标准或众所周知的表达式语言,例如反向波兰表示法,即RPN。见http://en.wikipedia.org/wiki/Reverse_Polish_notation。 RPN使用后缀表示法,允许用户通过定位和堆叠而不是使用括号来完全控制运算符优先级。这是以必须仔细(重新)命令操作数和操作为代价的。 (没有免费的午餐。)
将您的语言表达能力限制为某些特定模式,这些模式不需要更正常(中缀)语言的括号(具有运算符优先级)。
最后,如果你有一个用户界面来帮助用户组成他们的表达式(而不是文本语言),你可以做上面的#2之类的事情并使用用户定义子表达式的顺序来指示运算符优先级而不需要用于括号。基本上,您的UI将帮助他们构建表达式树。
最后,如果您的问题是如何为执行表达式而删除括号,这更像是代码生成问题。同样,RPN的堆栈可能很有用。或者,您可以将(可能是括号)表达式转换为通过附加(在编译器术语,临时)变量中显式连接的单个迷你(例如,三个操作数)语句。例如,(a + b) * c
变为t1 = a + b
,后跟final-result = t1 * c
。