这个作业属于哪个课程 | <网络1934-软件工程> |
---|---|
这个作业的要求在哪里 | <作业要求> |
这个作业的目标 | 实现一个自动生成小学四则运算题目的命令行程序 |
一、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
· Estimate | · 估计这个任务需要多少时间 | 605 | 590 |
Development | 开发 | ||
· Analysis | · 需求分析 (包括学习新技术) | 120 | 100 |
· Design Spec | · 生成设计文档 | 30 | 30 |
· Design Review | · 设计复审 | 30 | 30 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 20 | 20 |
· Design | · 具体设计 | 60 | 80 |
· Coding | · 具体编码 | 120 | 150 |
· Code Review | · 代码复审 | 30 | 30 |
· Test | · 测试(自我测试,修改代码,提交修改) | 90 | 90 |
Reporting | 报告 | ||
· Test Repor | · 测试报告 | 30 | 20 |
· Size Measurement | · 计算工作量 | 15 | 10 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 60 | 30 |
· 合计 | 605 | 590 |
二、效能分析
效能测试代码:
package main
import "testing"
func BenchmarkGenerate(b *testing.B) {
n = 10000
r = 10
for i := 0; i < b.N; i++ {
generateProblems()
}
}
func BenchmarkChekc(b *testing.B) {
exercisefile = "exercisefile.txt"
answerfile = "answerfile.txt"
for i := 0; i < b.N; i++ {
check()
}
}
产生题目耗时(执行4次):生成10000道题目平均耗时不到1s
阅卷模式耗时(执行1290次)
三、设计实现过程
核心思想:
算式计算:将运算式通过转化成逆波兰式来计算,双向链表代替栈来计算逆波兰式。
可以参考,里面波兰式讲的很全.
整数和真分数计算:用FAL分数结构来代替数值类型,整数也用FAL表示,支持加减乘除等分数类型的操作,需要加入真假分数的转换。
查重:时间原因,只是把结果重复的去掉。
异常:会出现除零,只能全局定义个bool来判断是否除零,处理结果跟查重一样,丢弃掉。
主要结构及其作用:
FAL和Sign都实现了Value接口的Len()类型
四、代码说明
//计算结果
func (p *Problem) Cal() *FAL {
var ll *list.List
//cnt := 0
ll = new(list.List)
for ele := p.postfixExpress.Front(); ele != nil; ele = ele.Next() {
//cnt++
kv := ele.Value.(*Entry)
if kv.kind == 1 {//kind=1,代表该元素不是运算符号
ll.PushBack(kv)
} else {
//fmt.Println(ll.Len(), kv.value.(*Sign).s)
ele1 := ll.Back()
ll.Remove(ele1)
ele2 := ll.Back()
ll.Remove(ele2)
kv1 := ele1.Value.(*Entry)
kv2 := ele2.Value.(*Entry)
fal1 := kv1.value.(*FAL)
fal2 := kv2.value.(*FAL)
sign := kv.value.(*Sign)
//fmt.Println(fal1, fal2)
switch sign.s {
case '-':
fal2 = Sub(fal2, fal1)
case '+':
fal2 = Add(fal2, fal1)
case '×':
fal2 = Mul(fal2, fal1)
case '÷':
fal2 = Div(fal2, fal1)
}
//将结果压入栈中
ll.PushBack(&Entry{
kind: 1,
value: fal2,
})
}
}
//fmt.Println(cnt)
return ll.Back().Value.(*Entry).value.(*FAL)
}
func main() {
s := time.Now()
rand.Seed(time.Now().UnixNano())
len := len(os.Args)
//必须输入两个参数-n -r或者-e -a
if len < 5 {
Usage()
}
ParseArgs()
//生成题目
if n > 0 {
generateProblems()
}
//阅卷模式
if exercisefile != "" && answerfile != "" {
check()
}
fmt.Println(time.Since(s))
}
五、运行测试
生成1w道题目
阅卷模式
六、项目小结
四则运算这个项目细节需要考虑的比较多,将字符串类型的算式通过一些方法计算出结果,需要细心分析,我因为没有完成一个模块就进行一次测试,所以花费了较长时间去调试,吸取教训,下次不会了。