第二章 逻辑–真与假的二元世界
为何逻辑如此重要
- 逻辑是消除歧义的工具
- 致对逻辑持否定意见的读者
乘车费用问题–兼顾完整性和排他性
- 车费规则、命题及其真假
- 有没有遗漏、有没有重复、注意边界值
使用 if 语句分解问题
- 逻辑的基本是两个分支
为何逻辑如此重要
逻辑是消除歧义的工具
自然语言极易产生歧义,连「或者」都不止一个正确意义
- 课前对话:按下紧急按钮或者水位高于危险水位时报警,「或者」是排他的吗
- 「他现在在大阪或者东京」,「或者」是排他的吗
规格说明书一般用自然语言描述,程序员必须走出歧义的迷宫
致对逻辑持否定意见的读者
- 计算机不按感情运行,逻辑上有错的程序不会正确运行
- 「逻辑冰冷且机械死板」正因如此才有用
- 程序员站在人类和计算机的分界线上
乘车费用问题–兼顾完整性和排他性
费用规则 A:6 岁以上的乘客 100 元,不到 6 岁的乘客 0 元
13 岁的 Alice 车费 100 元,4 岁的 Bob 车费 0 元
6 岁的 Charlie 车费 100 元,因为「6 岁以上」包含 6 岁
有没有「遗漏」:不管针对哪个乘客,都能判定命题的真假
- 规则 B「大于 6 岁 100 元 / 不到 6 岁 0 元」遗漏了正好 6 岁
有没有「重复」:要确认某位乘客是不是有两种费用标准
- 规则 C「6 岁以上 100 元 / 6 岁以下 0 元」,6 岁时两种费用都适用
- 规则 D 多写一条「正好 6 岁 100 元」,重复但不矛盾
画一根数轴辅助思考,命题为真的年龄范围用 ⊙ 标记,为假的用 ○ 标记
注意边界值,0 岁和 6 岁是边界所在,错误往往出在边界值上
规则 0~5 岁 6 岁 7 岁以上 问题 A 6 岁以上 / 不到 6 岁 0 元 100 元 100 元 无 B 大于 6 岁 / 不到 6 岁 0 元 无 100 元 遗漏 6 岁 C 6 岁以上 / 6 岁以下 0 元 100 元 / 0 元 100 元 重复 6 岁 兼顾完整性和排他性
- 没有遗漏即完整性,没有重复即排他性
- 大问题分解成小问题时,常用的方法就是检查完整性和排他性
命题及其真假
能够判断对错的陈述句叫做命题,命题正确称为真,不正确称为假
命题 真假 Alice(13 岁) 的年龄在 6 岁以上 真命题 Bob(4 岁) 的年龄在 6 岁以上 假命题 Charlie(6 岁) 的年龄在 6 岁以上 真命题 命题要么为 true 要么为 false,同时满足真和假的不能称为命题
#ruby |
使用 if 语句分解问题
把问题分解成命题为真和为假两部分
- 显示年龄在 6 岁以上的乘客的费用:显示 100 元
- 显示年龄不到 6 岁的乘客的费用:显示 0 元
这种分解就是程序里的 if 语句
#ruby |
逻辑的基本是两个分支
- 熟练的程序员不用特意想完整性和排他性也能写出 if 语句
- 可要写几十条、几百条 if 语句,组合中稍出点错就产生 bug
- 逻辑从根本上说是对完整性和排他性的组合表达