最小可重现例子(minimal reproducible example)是仍会产生错误结果的最小代码和数据,旁边写明预期输出和实际输出。你可以用它自己找出错误、用文字说明错误,或向老师求助。
这一课完成解题说明单元。当例子小到可以手动追踪时,会用到描述修正和把追踪表与输出联系起来。
怎样缩小出错的程序?
- 写下症状。 记录输入、预期输出和实际输出。
- 用固定值替换输入。 删掉
INPUT,改为赋予已知的数据。 - 一次删除一个无关部分。 去掉其他计算、提示信息和菜单。
- 每次删除后重新运行。 如果错误输出仍在,这次删除是安全的;如果输出改变或消失,把那一行放回去。
- 减少数据。 用最少、仍会出错的数值,并选容易计算的数字。
- 写出预期和实际输出, 并标明你怀疑的那一行。
例题
一个较长的程序把分数读入数组(array),然后求总和、平均值和最高分。总和不对。循环是:
Total ← 0
FOR Index ← 2 TO 5
Total ← Total + Scores[Index]
NEXT Index
第 1 步,症状。 对于五个分数,总和比预期的小。
第 2 步,固定数据。 删掉输入,改用三个分数:Scores[1] ← 10,Scores[2] ← 20,Scores[3] ← 30。
第 3 步,删除无关部分。 平均值和最高分不涉及 Total,删掉。把循环上限改成 3,与数据对应。
最小例子:
Scores[1] ← 10
Scores[2] ← 20
Scores[3] ← 30
Total ← 0
FOR Index ← 2 TO 3
Total ← Total + Scores[Index]
NEXT Index
OUTPUT Total
预期输出: 60(10 + 20 + 30)。实际输出: 50(20 + 30)。
为什么它指向错误。 循环从 2 开始,所以 Scores[1] 从未被加上。修正方法是让循环从 1 开始:FOR Index ← 1 TO 3。
检查。 每次删除之后,例子依然出错,而且短到四步就能追踪完。
要提防的错误
常见的失误是缩得太小,或者改变了问题:
Scores[1] ← 10 和 Total ← 0,没有循环。输出:0。
含有错误的循环被删掉了,所以例子不再显示问题。另一个失误是只交出例子,却没有预期输出,别人无从知道“错”是什么意思。
改正:每次删除后重新运行例子,确认实际输出仍然是错的。始终把预期输出和实际输出写在一起。
自我检测
1. 对于上面的 Total 错误,最小例子里必须保留哪些:(a) 输入姓名,(b) 循环,(c) 最高分计算,(d) 数组的值?
显示答案
保留 (b) 循环 和 (d) 数组的值。错误在循环里,数值能给出可检查的结果。输入姓名和最高分计算不影响 Total,可以删掉。
2. 把例子缩小到两个分数 10 和 20,保持同样有错的循环 FOR Index ← 2 TO 2。它还会显示错误吗?写出预期和实际输出。
显示答案
会。预期总和是 30(10 + 20)。循环只运行一次,Index = 2,所以只加上 Scores[2] = 20。实际总和是 20。错误依然存在,而且例子更容易追踪。
3. 一位学生说,一个统计大于 10 的数值个数的程序,对数据 5、10、15 输出 2,但应该是 1。写出最小例子的预期和实际输出,并指出可能的错误。
显示答案
预期:1,因为只有 15 大于 10。实际:2,因为代码把 10 和 15 都算进去了。可能的错误是用了 >= 10,而需要的是 > 10。数据 5、10、15 是很好的最小数据集,因为 10 正好在边界上。
接下来学什么
现在把五项技能综合起来,做解题说明练习。要记录反复出现的错误,错题记录与重测队列能帮你记下错误类型并安排重测。
如果你想有人陪你缩小一个难缠的程序,并讨论你的推理,我们的老师可以在线上一对一计算机科学补习中做到。