前些天测试程序,需要记录下程序不同模块的各自运行时间。
由于各个模块之间有各自的关联,运行时间会受到数据量大小的影响,所以只能一步一步运行并记录下时间再根据需要进行差值计算。
时间格式如此: XX(小时):XX(分钟):XX.XXX(秒) [注:秒精确到千分位]
但个别程序由于数据量过大,运行十分缓慢,需要记录的时间差值也很多,重复过程繁琐。
虽说算差值不是什么难事,都是些简单的数值计算,但是在面对上百个需要测试的程序,我实在是懒得去一个一个算。
正所谓“懒惰为人类进步的阶梯(误)”,因此,我萌生了使用Python编写一个可以进行时间差计算的小程序的想法。(2333...)
一、确定思路
1.在本程序中,我采用的是统一单位的方法。即先将时间统一为秒,再对其进行减法运算。那么我们只需要将这个过程通过代码复现即可。
2.在经过差值计算后,我们仍需要将结果重新格式化为原规定格式(XX:XX:XX.XXX)
3.鉴于需要重复使用,可以考虑加入循环,特定条件退出运算
二、拟定程序结构
本程序有五大部分:
(1).计算主函数
(2).格式化函数
(3).单位转换函数
(4).程序主函数
(5).调用主函数
三、编写程序
但是,在开始之前,我们需要知晓一件事。
我们程序在进行差值计算时,会精确到秒的千分位,按理说我们定义浮点数据类型即可。
然而,在计算机中,采用浮点数进行计算无法达到“精确到xx位小数点”的精度。
为什么呢?我们实验一下:
首先定义两个浮点数
然后我们进行加法运算
这里就出了问题,答案并不是我们想要的6.3,而是不知什么鬼的6.300000000000001。
这里面最重要的原因就是,计算机采用二进制存储数据,使用浮点数并不能很好的表示十进制数据,会有一些"小误差"。
那我们如何才能做到十进制精确计算呢?
答案就是使用Python内置模块decimal,它可以帮助我们把浮点数转化为十进制类型,并且支持所有常用数学运算
示例:
1 from decimal importDecimal2
3 a = Decimal('4.2')4 b = Decimal('2.1')5
6 print(a + b)
结果:
我们发现,结果不再是鬼畜的6.300000000000001,是正常的6.3。
而且可以观察到,经过Decimal转化得到的是一个Decimal对象,使用时需要注意,在转化浮点数时,需要其字符串化。
那么解决了精确运算的问题,我们现在可以进行程序的编写了。
1.首先是计算主函数:
我们进行时间差计算,需要两个参数,起始时间和结束时间
然后将两参数单位统一,得到统一单位后的时间差值,再对其进行格式化以及格式的还原即可
本程序中计算主程序即是对参数单位进行统一的函数,代码如下:
(当然在程序开头要声明引入Decimal)
1 def Time_Cal(): #定义函数
2 print("----------------XX:XX:XX----------------") #打印分行符
3 #程序运行后在这里输入起始时间和结束时间
4 start_time = input("Enter your Start Time:")5 stop_time = input("Enter your Stop Time:")6 #使用split方法对输入的字符串以“:”为分隔符进行分割处理,并存为列表
7 start_list = start_time.split(':')8 stop_list = stop_time.split(':')9 #再通过不同单位划分三个部分,分别从列表获取小时、分钟、秒的值
10 start_hour =Decimal(start_list[0])11 start_minu = Decimal(start_list[1])12 start_sec = Decimal(start_list[2])13 stop_hour =Decimal(stop_list[0])14 stop_minu = Decimal(stop_list[1])15 stop_sec = Decimal(stop_list[2])16 #这里就是对获取到的各个部分的值进行单位统一(基本单位为秒)
17 value_start = start_hour * 3600 + start_minu * 60 +start_sec18 value_stop = stop_hour * 3600 + stop_minu * 60 +stop_sec19 returnvalue_stop,value_start20 #返回单位统一后的起始时间和结束时间,此时这两个参数均以秒数为单位
2.格式化函数:
这里格式化的原因是因为在我们计算结束后,有些位置的值为各位数,因标准格式(XX:XX:XX.XXX)规范,这里直接对缺位处进行补零
但这里有三点要考虑,即:小时位是否需要补零、分钟位是否需要补零、秒位是否需要补零
所以我们需要对小时、分钟、秒三部分进行判断:
同样,当时间值只有分钟秒数甚至只有秒数时也要进行类似判断。
那么在这种情况下,我们则优先对秒数处格式化函数进行定义,这样在后面判断分钟和小时是否需要补零时可以直接调用函数,减少代码量。
代码:
1 defS_Formatting(len_s,s):
2 #这里我们先定义对秒处进行格式化函数
3 if len_s < 2: #判断秒数位是否为个位数
4 s_sec = '0' + s #个位则补零
5 else:
6 s_sec = s #反之则直接向下传递
7 return s_sec #返回秒数位置的最终值
之后对分钟和小时处判断,直接调用即可:
对分钟:
1 def M_Formatting(len_m,m,len_s,s): #注意这里参数要包含秒数位的值
2 if len_m < 2:3 s_minu = '0' +m4 s_sec = S_Formatting(len_s,s) #判断秒数位时直接调用即可
5 else:6 s_minu =m7 s_sec =S_Formatting(len_s,s)8 return s_minu,s_sec #返回分钟和秒数的最终值
对小时:
1 def H_Formatting(len_h,h,len_m,m,len_s,s): #参数同样要包含分钟和秒数值
2 if len_h < 2:3 s_hour = '0' +h4 s_minu,s_sec = M_Formatting(len_m,m,len_s,s) #调用分钟格式化函数
5
6 else:7 s_hour =h8 s_minu,s_sec =M_Formatting(len_m,m,len_s,s)9 return s_hour,s_minu,s_sec #返回小时、分钟、秒数的最终值
3.单位转换函数:
单位转换函数是在单位统一后,格式化之前,对传入的起始时间和结束时间进行差值运算后,通过秒数值的大小判断分钟或者秒数位是否需要进位。
并在转换单位后调用格式化函数并将其组合为规定格式(XX:XX:XX.XXX)返回最终值。
代码:
1 def Switch(value_stop,value_start): #这里传入转化为秒的起始时间和结束时间
2 D_value = Decimal(value_stop - value_start) #计算得到时间差,为达到精确计算,调用Decimal方法
3 #从这里开始对是否需要进位进行判断
4 if D_value >= 3600: #这里是小时位需要进位的情况
5 D_hour = int(D_value) #取整,去掉小数点
6 hour = D_hour // 3600 #同样取整,做除
7 D_minu = D_hour - hour * 3600 #得到包含分钟位的值
8 minu = D_minu // 60 #取整,做除
9 sec = D_value - hour * 3600 - minu * 60 #用时间差减去得到的小时和分钟就是秒数的值
10
11 #调用格式化函数
12 s_hour,s_minu,s_sec =H_Formatting(len(str(hour)),str(hour),len(str(minu)),str(minu),len(str(int(sec))),str(sec))13 print("The Time Difference is:" + s_hour + ':' + s_minu + ':' + s_sec) #组合为规范格式输出
14 elif 60 <= D_value < 3600: #这里是分钟位进位的情况,小时值为零
15 minu = D_value // 60
16 sec = D_value - minu * 60
17 s_minu,s_sec =M_Formatting(len(str(minu)),str(minu),len(str(int(sec))),str(sec))18 print("The Time Difference is:" + '00:' + s_minu + ':' +s_sec)19 else: #仅有秒数值的情况
20 sec =D_value21 s_sec =S_Formatting(len(str(int(sec))),str(sec))22 print("The Time Difference is:" + '00:' + '00:' + s_sec)
最后编写主函数调用函数即可。
运行结果:
1 from decimal import Decimal #调用Decimal模块
2
3 defTime_Cal():4 print("----------------XX:XX:XX----------------")5 start_time = input("Enter your Start Time:")6 stop_time = input("Enter your Stop Time:")7 start_list = start_time.split(':')8 stop_list = stop_time.split(':')9 start_hour =Decimal(start_list[0])10 start_minu = Decimal(start_list[1])11 start_sec = Decimal(start_list[2])12 stop_hour =Decimal(stop_list[0])13 stop_minu = Decimal(stop_list[1])14 stop_sec = Decimal(stop_list[2])15 value_start = start_hour * 3600 + start_minu * 60 +start_sec16 value_stop = stop_hour * 3600 + stop_minu * 60 +stop_sec17 returnvalue_stop,value_start18
19 defS_Formatting(len_s,s):20 if len_s < 2:21 s_sec = '0' +s22 else:23 s_sec =s24 returns_sec25
26 defM_Formatting(len_m,m,len_s,s):27 if len_m < 2:28 s_minu = '0' +m29 s_sec =S_Formatting(len_s,s)30 else:31 s_minu =m32 s_sec =S_Formatting(len_s,s)33 returns_minu,s_sec34
35 defH_Formatting(len_h,h,len_m,m,len_s,s):36 if len_h < 2:37 s_hour = '0' +h38 s_minu,s_sec =M_Formatting(len_m,m,len_s,s)39 else:40 s_hour =h41 s_minu,s_sec =M_Formatting(len_m,m,len_s,s)42 returns_hour,s_minu,s_sec43
44 defSwitch(value_stop,value_start):45 D_value = Decimal(value_stop -value_start)46 if D_value >= 3600:47 D_hour =int(D_value)48 hour = D_hour // 3600
49 D_minu = D_hour - hour * 3600
50 minu = D_minu // 60
51 sec = D_value - hour * 3600 - minu * 60
52
53 s_hour,s_minu,s_sec =H_Formatting(len(str(hour)),str(hour),len(str(minu)),str(minu),len(str(int(sec))),str(sec))54 print("The Time Difference is:" + s_hour + ':' + s_minu + ':' +s_sec)55 elif 60 <= D_value < 3600:56 minu = D_value // 60
57 sec = D_value - minu * 60
58 s_minu,s_sec =M_Formatting(len(str(minu)),str(minu),len(str(int(sec))),str(sec))59 print("The Time Difference is:" + '00:' + s_minu + ':' +s_sec)60 else:61 sec =D_value62 s_sec =S_Formatting(len(str(int(sec))),str(sec))63 print("The Time Difference is:" + '00:' + '00:' +s_sec)64
65 def main(): #定义主函数
66 running =True67 print("Hello ~~ !")68 while running: #通过循环方便输入和计算
69 value_stop,value_start = Time_Cal() #调用计算主函数
70 Switch(value_stop,value_start) #调用单位转换函数
71 action = input("Go on ? Y/N:")72 if action == 'Y' or action == 'y':73 running =True74 elif action == 'N' or action == 'n':75 running =False76 print("Goodbye~~")77
78 if __name__ == '__main__': #调用主函数
79 main()
查看完整代码