55

假如你的同事写了这样的代码:a && d || b && c && !d || (!...

 4 years ago
source link: https://juejin.im/post/5e078eede51d45583a66d1e0
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

假如你的同事写了这样的代码:a && d || b && c && !d || (!a || !b) && c

2019年12月29日阅读 19545

假如你的同事写了这样的代码:a && d || b && c && !d || (!a || !b) && c

假设看到了这样的代码:

if (a && d || b && c && !d || (!a || !b) && c) {
  console.log('pass')
} else {
  console.log('fail')
}
复制代码

你是否一口老血喷在屏幕上?

当然,这段代码是我参考一个掘金沸点(@隔壁村的李二狗)伪造的,但愿你和你的同事都别这么写。

能写出这种与或非,如果不是逻辑不清,那么估计只有一种可能,需求变更很多次,多人修改后的结果。。

现在的问题是,面对如此代码,这么复杂的逻辑,能否优化?

答案是肯定的!

这种问题的探究来自于一门数学:布尔代数或逻辑代数。

说到布尔,我们开发者对此太熟悉了。不就是 true 和 false 嘛。

布尔代数这门课,大学里应该或多或少都讲些吧。因为我是数学专业毕业的,看到这种问题必须记录一下,也顺便复习一下。

为了方便表达,JS中的与或非,我用布尔代数里面的表示方法(感谢掘金支持latex公式):

a\&\&b \Rightarrow AB

a||b \Rightarrow A+B

!a \Rightarrow \overline{A}

因此 a && d || b && c && !d || (!a || !b) && c 可以表达为:

AD+BC\overline{D}+(\overline{A}+\overline{B})C

转化后优先级清晰多了。

现在的问题是,我们如何化简这个逻辑表达式。

还好有一些常用结论可供我们使用:

  1. A+A=A、A+\overline{A}=1

  2. AB+A\overline{B}=A

  3. A+AB=A

  4. \overline{A}+\overline{B}=\overline{AB}、\overline{A}\overline{B}=\overline{A+B}

  5. AB+\overline{A}C=AB+\overline{A}C+BC

前四个公式很好理解。比如A+\overline{A}=1,自己或上自己否,当然为 true。

关键在于第5个公式没那么直观,可以通过画图简单说明下(其他公式都可以类似推导)。

首先看AB部分,如图中绿色区域:

1

再看\overline{A}C,如图中绿色区域:

1

则二者之和为:

1

BC部分正是图中粉色区域:

1

因为粉色区域原本就在前二者之和里面,因此加多少BC次都是一样的。

注意最后这个公式核心特点:A\overline{A}是以和出现的。

有了这几个公式作为铺垫,我们就可以正式推导了(原沸点配图中有):

AD+BC\overline{D}+(\overline{A}+\overline{B})C

根据第4条,替换最后一项:

AD+BC\overline{D}+\overline{AB}C

注意到前两项分别有D\overline{D},符合第5条:

AD+BC\overline{D}+ABC+\overline{AB}C

此时最后两项,符合第2条:

AD+BC\overline{D}+C

最后两项,其中一项为C,另外一项也包含C,满足第3条:

AD+C

至此化简完了。真是不可以思议,B没了!

此时开篇的代码简化成了这样:

if (a && d || c) {
  console.log('pass')
} else {
  console.log('fail')
}
复制代码

点击验证二者等价性

感谢你看到这里,希望有所帮助。

另外,在2019年末,立了个flag,数学和动画将是我今年的核心输出点。

1

图中二维码是我的唯一微信号,如有朋友想加的,麻烦备注下来源哈,比如“掘金”。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK