为啥用析取范式表达代码很重要?
Posted
技术标签:
【中文标题】为啥用析取范式表达代码很重要?【英文标题】:Why is it important to express code in Disjunctive Normal Form?为什么用析取范式表达代码很重要? 【发布时间】:2011-07-04 18:26:33 【问题描述】:在我工作的公司,最近有一项要求,所有“高度可见”的布尔逻辑必须以析取范式表示。
例如(尽管这个概念与语言无关),
#if (defined(A) || defined( B )) || (defined(C) && defined(D))
必须替换为:
#if defined(A) || (defined(C) && defined(D)) || defined(B)
要求必须以这种方式表达代码的动机是什么?有什么优势?
【问题讨论】:
两个表达式都在 DNF 中;第一个只是有一些多余的括号。这是您的编码指南中的实际示例吗? 该示例来自最近的一个电子邮件链,该电子邮件链要求基于 DNF 进行更改。为这个错误道歉,因为它确实是一个糟糕的例子。 【参考方案1】:优势在于,在代码库中的任何地方以规范/规范化形式表达此类逻辑(理论上)将使程序员更容易理解和维护它。
如果没有这样的规则,一些程序员倾向于尝试“优化”一个表达式,这样维护者就很难解开它。此外,如果有必要,通用形式可以更轻松地编写新表达式。
(这些优势值得商榷。与任何风格准则一样,遵循一致的规则比选择一条规则而不是替代规则更重要。)
【讨论】:
【参考方案2】:虽然你的例子很糟糕(两个表达式都在 DNF 中),但我明白为什么有人会强加这个政策。
任何范式的优点是所有表达式现在都具有相同的形式。在 DNF 中,该形式是子句/条件的列表,其中一个必须为真。子句依次是文字/条件列表,每个条件都必须为真。
DNF 特别有一个优势,在大多数语法中,and 的优先级高于 or,而 not 的优先级更高,所以 DNF需要的括号比 CNF 少,省略括号不是错误。
【讨论】:
【参考方案3】:很多时候,您拥有的编码标准并不像始终如一地实施它们那么重要。始终如一地编写代码大大提高了可读性,而且很多时候,决定选择哪些代码的人是在行使个人偏好,而不是编码智慧。
假设您列出的标准确实有帮助。我想说大多数人没有意识到 && 运算符比 || 具有更高的运算符优先级。因此,在 && 运算符和操作数周围使用 () 有助于使事情更加明确。
请始终记住,在许多语言中,如果仅在计算其中一个操作数后可以确定表达式的值,则可能不会执行布尔表达式的两个操作数。如:
1: (trueMethod() || falseMethod())
2: (falseMethod() || trueMethod())
万一只有一个 trueMethod() 被执行。但在案例 2 中,两种方法都被执行。顺序可以产生很大的影响。
【讨论】:
以上是关于为啥用析取范式表达代码很重要?的主要内容,如果未能解决你的问题,请参考以下文章
数理逻辑命题逻辑的等值演算与推理演算 ( 命题逻辑 | 等值演算 | 主合取 ( 析取 ) 范式 | 推理演算 ) ★★