文章目录

  • 一个错误题解
  • 单元测试发现错误
  • 更正错误
  • 再次发现错误和更正
  • 总结和问答练习

时效性
本篇撰写时间为2021.11.13,由于计算机技术日新月异,博客中所有内容都有时效和版本限制,具体做法不一定总行得通,链接可能改动失效,各种软件的用法可能有修改。但是其中透露的思想往往是值得学习的。
Windows 10家庭中文版,版本20H2,操作系统内部版本19042.1288
本篇前置:

  • ExpRe[3] python[0] Anaconda配置python环境
    https://www.cnblogs.com/minor-second/p/15549061.html
  • python3的基础,动态规划算法基础。大致知道类继承的意思。

一个错误题解

我们看到一道普通的算法题:

给定实数列 { x i } i = 1 n \{x_i\}_{i=1}^n {xi​}i=1n​,要确定 1 ≤ i ≤ j ≤ n 1\le i\le j\le n 1≤i≤j≤n,使得 ∑ k = i j x k \sum_{k=i}^j x_k ∑k=ij​xk​最小。请编制时间复杂度为 O ( n ) O(n) O(n)的算法求解该问题。

由于算法课上只用交伪码,不知道自己写的究竟对不对,于是我们想用单元测试检查算法正确性。
在上一期创建的python环境中,新建.py文件,写一个简单的动态规划。

def find_min_sub(n, x):assert isinstance(x, tuple), 0assert all(isinstance(x[i], float) for i in range(len(x))), 1assert isinstance(n, int) and n > 0, 2assert len(x) == n, 3global_min = [0, 1, x[0]]marginal_min = [0, 1, x[0]] if x[0] < 0 else [1, 1, 0]for i in range(1, n):if marginal_min[2] + x[i] >= 0:marginal_min = [i+1, i+1, 0]else:marginal_min[1] = i+1marginal_min[2] += x[i]if marginal_min[2] < global_min[2] and marginal_min[0] < marginal_min[1]:global_min = marginal_minif x[i] < global_min[2]:global_min = [i, i+1, x[i]]return global_min[0]+1, global_min[1]
print(find_min_sub(5, (0., -1., 0.5, -0.6, 0.)))

其实这是错误的,你发现问题在哪里了吗?
但是直接Ctrl+F5运行,没有任何问题。正确输出(2, 5),表示 − 1 + 0.5 − 0.6 + 0 -1+0.5-0.6+0 −1+0.5−0.6+0这个求和满足题意,最小。

单元测试发现错误

新建一个文件用于单元测试。

对拍是一种进行检验或调试的方法,通过对比两个程序的输出来检验程序的正确性。可以将自己程序的输出与其他程序的输出进行对比。 (OI Wiki)

比如把暴力方法和自己写的方法对比。

import unittest
import random
from problem1 import find_min_sub
class Test(unittest.TestCase):  # 编写自己的测试类,继承指定类def test_manual(self):  # test开头的才被认为测试方法,测试时才被执行i, j = find_min_sub(5, (0., -2., 1., -2., 3.))self.assertEqual(i, 2)self.assertEqual(j, 4)i, j = find_min_sub(10, (0.1, -2., -2., -7., 10., -3., -3., -5., 2., -1.))self.assertEqual(i, 2)self.assertEqual(j, 8)def test_assertion(self):with self.assertRaises(AssertionError):find_min_sub(1, (0.,0.))find_min_sub('', '')def test_auto(self):n = random.randrange(1, 1000)x = tuple(random.random() * 10 - 5 for _ in range(n))start, end, min_value = 0, 0, float('inf')for s in range(n):for e in range(s+1, n):v = sum(x[s:e])if v < min_value:start, end, min_value = s, e, vstart += 1     i, j = find_min_sub(n, x)       self.assertEqual(start, i, msg=(n, x))self.assertEqual(end, j, msg=(n, x))if __name__ == '__main__':unittest.main()

运行,发现报告有

Ran 3 tests in 0.672sFAILED (failures=2)

我们发现手工编写的长一点的测试例就出错了。于是去仔细检查代码。

更正错误

我们发现函数find_min_sub倒数第4行末尾少了[:](或:.copy()),导致两个list之间修改一个也修改另一个。
这是使用python一个常见大坑:可变(mutable)对象
更正错误之后,保存文件,运行测试文件test1.py。输出

(2, 4)
...
----------------------------------------------------------------------
Ran 3 tests in 0.122sOK

然而以上仍有错误,你发现了吗?

再次发现错误和更正

我们仍然不放心,更改test_auto函数为循环100次。

    def test_auto(self):for _ in range(100):n = random.randrange(1, 1000)x = tuple(random.random() * 10 - 5 for _ in range(n))start, end, min_value = 0, 0, float('inf')for s in range(n):for e in range(s+1, n):v = sum(x[s:e])if v < min_value:start, end, min_value = s, e, vstart += 1     i, j = find_min_sub(n, x)       self.assertEqual(start, i, msg=(n, x))self.assertEqual(end, j, msg=(n, x))

发现仍然出现了错误(但错误出现的频率并不高)。一个典型错误例:

(8, (2.2805755721332455, 1.1867061512050858, -2.061145458146788, -2.0107648781130516, 4.032469478859333, -2.184053441010362, 4.834683794987862, -4.984215701600048))

反复运行,发现错误总是和数组末尾有关。
经过仔细检查,发现是对拍的暴力方法写错了。for e in range(s+1, n):应该是for e in range(s+1, n+1):.
再次运行,发现对100次自动生成的测试过了。

总结和问答练习

  1. Q: 之前写的测试真的可以充分发现出算法的错误吗?试写出一个(极大概率能)通过测试的错误算法。
    A:
def find_min_sub(n, x):assert isinstance(x, tuple), 0assert all(isinstance(x[i], float) for i in range(len(x))), 1assert isinstance(n, int) and n > 0, 2assert len(x) == n, 3global_min = [0, 1, x[0]]marginal_min = [0, 1, x[0]] if x[0] < 0 else [1, 1, 0]for i in range(1, n):if marginal_min[2] + x[i] >= 0:marginal_min = [i+1, i+1, 0]else:marginal_min[1] = i+1marginal_min[2] += x[i]if marginal_min[2] < global_min[2] and marginal_min[0] < marginal_min[1]:global_min = marginal_min[:]return global_min[0]+1, global_min[1]

此时对于恒正的数据就极有可能输出错误结果。但它极有可能通过100次前述测试。
这说明完全随机生成测试数据有缺陷。

  1. Q: 完全随机生成测试数据还可能有什么缺陷?举例说明。
    A:
  • 不利于考察最坏时间复杂度。
  • 当实际问题的系统有很多assert断言条件时纯随机数据会有大量平凡的非法例等。
    注:因此我们之后将探索用约束求解生成测试例的技术。
  1. Q: 运行test.py时,为什么输出了(2, 4)这种字样?
    A: import模块时,会自动执行其中的语句,如print

模块可以包含可执行的语句以及函数定义。这些语句用于初始化模块。它们仅在模块第一次在import语句中被导入时才执行。(当文件被当作脚本运行时,它们也会执行)
实际上,函数定义也是“被执行”的“语句”;模块级函数定义的执行在模块的全局符号表中输入该函数名。 (docs.python.org)

ExpRe[4] python[1] 单元测试,算法题对拍相关推荐

  1. python代码基础题-python每日经典算法题5(基础题)+1(中难题)

    现在,越来越多的公司面试以及考验面试对算法要求都提高了一个层次,从现在,我讲每日抽出时间进行5+1算法题讲解,5是指基础题,1是指1道中等偏难.希望能够让大家熟练掌握python的语法结构已经一些高级 ...

  2. python全排序算法题_Python的100道经典算法题(1)

    按照c语言的100道经典算法题,自己原创写的,就得是自己的练习题了 [程序1] 题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 程序分析:可填在百位.十位.个位的数 ...

  3. python每日经典算法题5(基础题)+1(较难题)

    一:基础算法题5道 1.阿姆斯特朗数 如果一个n位正整数等于其各位数字的n次方之和,则称该数为阿姆斯特朗数.判断用户输入的数字是否为阿姆斯特朗数. (1)题目分析:这里要先得到该数是多少位的,然后再把 ...

  4. python每日经典算法题5(基础题)+1(中难题)

    现在,越来越多的公司面试以及考验面试对算法要求都提高了一个层次,从现在,我讲每日抽出时间进行5+1算法题讲解,5是指基础题,1是指1道中等偏难.希望能够让大家熟练掌握python的语法结构已经一些高级 ...

  5. 100个灯泡python编程_算法题:一个圆环上有100个灯泡,灯泡有打...

    算法题:一个圆环上有100个灯泡,灯泡有打开关闭两种状态,灯泡状态随机,按一个灯泡,相邻两个灯泡的状态也会改变. eg: ' 暗 - 亮 - 暗 ' 按中间灯泡 ,变化为 ' 亮 - 暗 - 亮 '. ...

  6. [Python面试][基础算法题]Python基础面试(基础算法题目较多)

    Python基础 文件操作 1.有一个jsonline格式的文件file.txt大小约为10K 2.补充缺失的代码 模块与包 3.输入日期, 判断这一天是这一年的第几天? 4.打乱一个排好序的list ...

  7. LeetCode 204. Count Primes--从一开始的质数个数--Python解法--面试算法题

    题目地址:Count Primes - LeetCode Count the number of prime numbers less than a non-negative number, n. E ...

  8. LeetCode 2. Add Two Numbers--C++,Python解法--面试算法题

    题目地址:Add Two Numbers - LeetCode You are given two non-empty linked lists representing two non-negati ...

  9. Python蓝桥杯算法题--从入门到精通 30天强化实训 |CSDN独创

    [编程入门]温度转换 输入一个华氏温度,要求输出摄氏温度.公式为 c=5(F-32)/9,取位2小数. 一个华氏温度,浮点数 F=float(input()) c=(5*(F-32)/9) c=&qu ...

最新文章

  1. 「AI不惑境」数据压榨有多狠,人工智能就有多成功
  2. nginx负载均衡的策略
  3. MySQL-性能优化_大表和大事务的常用处理方案
  4. 【ABAP】CK11N相关Table
  5. 抢红包的红包生成算法
  6. HDU-6290 奢侈的旅行 2018女赛 Dijkstra堆优化
  7. 7-4 输出最小公倍数 (9 分)
  8. 发邮件请领导审批文件怎么说_住建部:1月1日起,两项甲级资质实行告知承诺审批!...
  9. pythondis功能_python 使用 Dis 模块进行代码性能剖析
  10. Flex 加载pdf
  11. css 设置表格右边有图片_我写CSS常用的方法
  12. 教你编写高质量的 Java 代码!
  13. 深入浅出设计模式(一):单例模式
  14. 微软官方提供的免费正版 Windows 8.1/Win10/7/XP/Vista 操作系统虚拟机镜像下载
  15. 【Linux】Debian 连接惠普打印机并共享
  16. wiki admin.php,dokuwiki 重置管理员密码
  17. 360路由器的虚拟服务器设置,360路由器手机设置方法 | 192路由网
  18. Unbox failed! RequestError: Error: connect ETIMEDOUT 151.101.76.133:443
  19. 最美的公式:你也能懂的麦克斯韦方程组(微分篇)
  20. java开发一款雷电游戏

热门文章

  1. 小程序毕设作品之微信校园维修报修小程序毕业设计成品(8)毕业设计论文模板
  2. WGAN-GP解读分析
  3. JAVA程序设计(01.1)-----英制公制,单位转换
  4. apriori算法_挖掘频繁模式、关联和Apriori算法
  5. 城步一中2021高考成绩查询,教师平凡的选择——学考前的城步一中杨美玉
  6. mirdeep2识别novel miRNA
  7. ubuntu配置多网段IP
  8. Vertx之Junit单元测试
  9. Java JAN学习
  10. Xournal-条记抄写软件