第一次作业

(你没看错,就一个类。。。)

通过正则表达式处理输入的字符串,提取出每一项的系数和指数,在输出的时候,应当考虑到合并同类项和正项提前的问题,使得最终的输出最短。

我第一次作业的代码超级难看,在互测的时候看了别人的代码之后,自己的代码连我自己都看不下去了。在第一次作业的代码中,我只用了一个主类Main,在主方法中用大正则识别表达式、判断合法性、求导,毫无对象概念,根本没有体现出面向对象的特性,同样也在互测环节中被查出来很多bug。所以在第二次作业中,我决定使用面向对象的思想,对代码进行一次彻底的重构。

公测没有查出bug,但是在互测环节被hack惨了。

最主要的问题就是输入x-x或者123这类求导结果为0的公式没有输出的问题,其次还有特殊字符、正则爆栈的问题,其中第一个问题是最明显的问题。这是因为我在写程序的时候没有模块化的概念,完完全全是面向过程式的写法,导致自己的程序很不清晰。在自己写完代码、通过弱侧之后,应当自己编写测试点并测试,而我显然是因为没做好在本地机器上测试的工作,才会出现这么明显的bug。

第二次作业

与第一次作业类似,在输入完公式之后进行化简,使得每一项都是t*x^a*sin(x)^b*cos(x)^c的形式,然后进行求导,最后再合并同类项,把正项提前输出。但是,应当注意+++123是一个合法的公式,可以看作第一个加号是项的符号,第二个加号是"1*"的省略,第三个加号是123的符号,应当特殊处理一下。

我使用了4个类:Main主类;Exp公式类,由很多Term通过加法构成;Term项类,由很多Factor通过乘法构成;Factor因子类,里面有一个枚举变量,用于区分这是什么类型的因子。

公测还是没查出bug,但是在互测环节被别人查出来了。

这一次的bug明显比第一次少了,但是还有bug,在公式末尾为+或-的时候,会产生异常(由于str.indexOf(i)越界了)。

第三次作业

由于这次作业需要支持函数嵌套,因此在第二次作业的基础上,进行了大量的改造。

我使用了5个类:Main主类;Exp公式类,由很多Term通过加法构成;Term项类,由很多Nest通过乘法构成;Nest类,是很多Func的嵌套,还包含了exp代表嵌套在最里层的公式;Func函数类,由第二次作业的Factor改造而成,把常数看作常值函数,仍然用枚举变量的方式区分不同的函数。

对于Exp公式类的求导,就是对其中的Term求导然后相加;对于Term的求导,通过乘法的求导法则,最终返回一个Exp;对于Nest的求导,通过链式法则,最终返回一个Term。

同样地,公测还是全AC,互测被查出来了bug,在Nest最后如果是sin(x) ^ +2这样,^和指数的符号中间有空格的时候会出现问题,是因为我在空格的地方没有处理好。

总结

通过观察这三次作业的UML图和Class Metrics表,可以看出第二、三次作业相比第一次作业的进步很大(第一次作业我就不说什么了),这三次作业的bug全是出现在表中标红的地方,在接下来的程序中,我应当改进程序的逻辑,使得程序质量得到提高,逻辑更加清晰。

互测发现别人bug的策略

我用PowerShell写了一个自动测试的脚本,用Python写了一个表达式求导的程序和判断两个公式是否相等的程序(都是用的Sympy库),在第三次作业中查出了别人求导结果错误的地方。

test.ps1内容如下

$rootPath=$(pwd).Path
$name="sympy","archer","assassin","berserker","caster","lancer","rider","saber"
$entrance="","Main","Main","Main","Main","Main","Main","Main" # 把这里稍微改一下,因为有些人主类不是Main
$ans=0..7
for(;;) {
   cd $rootPath
   $str=Read-Host
   if($str -eq "init") {
       for($i=1;$i -le 7;$i++) {
           echo "Compiling $($name[$i])"
           cd "$rootPath\$($name[$i])\src"
           javac -encoding utf-8 (dir . -recurse -name *.java)
           echo ""
       }
       echo "finish"
       continue
   } elseif($str -eq "exit") {
       exit
   }

   echo "***$($name[0])***:"
   $ans[0]=(echo $str|python $rootPath\ans.py)
   echo $ans[0]
   echo ""

   for($i=1;$i -le 7;$i++) {
       echo "$($name[$i]):"
       cd "$rootPath\$($name[$i])\src"
       $ans[$i]=(echo $str|java $entrance[$i]|Select-Object -First 1)
       echo $ans[$i]
       cd $rootPath
       if($ans[$i] -ne "WRONG FORMAT!") {
           echo $ans[0] $ans[$i]|python check.py
       }
       echo ""
   }
}

ans.py内容如下

from sympy import *
x = Symbol('x')
str = input()
print(diff(str, x))

check.py参考了评测机的评测方式,内容如下

from sympy import *
import random
str1 = input()
str2 = input()
expr1 = simplify(str1)
expr2 = simplify(str2)
flag = true
for i in range(0,100):
   tmp = random.uniform(-10,10)
   r1 = expr1.evalf(subs={'x':tmp})
   r2 = expr2.evalf(subs={'x':tmp})
   if abs(r1-r2) > 0.0001:
       flag = false
       break
if flag == true:
   print("AC")
else:
   print("WA")

重构和改进的措施

对于第一次作业而言,我可以使用Exp公式类和Term项类,而不是我原来的完全面向过程的方式,使得自己在编程的时候不容易出现bug。

第二次作业和第三次作业完全可以使用继承的方式,而不是使用枚举变量,这样可以让我的程序看起来更清晰,更能体现面向对象的思想。

对于第二次作业而言,我可以使用sin(x)^2+cos(x)^2=1这个恒等式,对求导结果进行化简,使得输出长度更短。

对于第三次作业而言,我可以把含有0的Term删除,把所有最终为常数的Nest乘在一起,可以让最终结果更短。

这三次作业的bug都出现在程序特别”面向过程“的部分,我应当对其进行改造。

2019OO第一单元总结的更多相关文章

  1. 2019OO第一单元作业总结

    OO第一单元作业的主题是求导,下面将分三次作业分别总结一下. --------------------------------------------------------------------- ...

  2. OO第一单元作业小结

    前言 第一单元的主题是表达式求导,第一次作业是只带有常数和幂函数的求导,第二次作业加入了正余弦函数,第三次作业又加入了表达式嵌套,难度逐渐提升.总体来说前两次作业还易于应对,而第三次作业做得相对有些艰 ...

  3. BUAA面向对象设计与构造——第一单元总结

    BUAA面向对象设计与构造——第一单元总结 第一阶段:只支持一元多项式的表达式求导 1. 程序结构 由于是第一次接触面向对象的编程,加之题目要求不算复杂,我在第一次作业中并没有很好利用面向对象的特点, ...

  4. 2019_BUAAOO_第一单元总结

    前言 OO第一单元共有三次作业,分别为多项式求导.带有三角函数与幂函数的表达式求导.带有嵌套表达式因子的表达式求导.虽然这三次作业都离不开求导,可是每次作业的复杂度都是大大递增的.对于习惯于面向过程编 ...

  5. OO第一单元作业总结

    oo第一单元的作业是对多项式的求导.下面就是对三次作业分别进行分析. 第一次作业 分析 第一次作业相对来讲比较简单,甚至不用面向对象的思想都能十分轻松的完成(实际上自己就没有使用),包含的内容只有常数 ...

  6. OO第一单元总结

    OO第一单元作业总结 一.前言 开学四周,不知不觉已经做了三次OO作业.事实上,每一次作业对我来说都是很大的挑战,需要花费大量的时间和精力来学习. 虽然学得很艰苦,但最后还是连滚带爬地完成了.(好惨一 ...

  7. 2019OO第二单元总结

    (1)设计策略 电梯第1次作业是一个傻瓜调度电梯,使用先来先服务原则,不用考虑捎带(可以认为电梯的载客量为1),因此比较简单,调度器用一个队列就可以. 使用生产者-消费者模型,输入线程是生产者,电梯是 ...

  8. OO第一次博客作业--第一单元总结

    OO第一单元总结 面向对象设计与构造的第一单元,对“面向对象”的概念还根本不理解不熟悉,只觉得需要“分模块”,但不知道怎么分,分多少模块,怎么根据需要的模块的功能建立类.学习的进度又太慢,根本跟不上出 ...

  9. OO第一单元总结(表达式求导)

    写在前边:第一次接触面向对象语言,编程思想仍然不可避免的有以前面向过程的影子.从第一次作业的完全面向过程,到第二次学会剥离各个类互不影响到第三次作业的先构思面向对象的基本程序架构再编程.虽然程序有些地 ...

随机推荐

  1. win10设置vscode的终端为管理员权限

    右击vscode 点击属性选择兼容性,勾选 “以管理员身份运行此程序” 确定即可!

  2. aiohttp使用队列

    获取百度的搜索结果,然后把百度的长链接,获取到真实的url import time import aiofiles import aiohttp import asyncio from lxml im ...

  3. 记录一次Python下Tensorflow安装过程,1.7带GPU加速版本

    最近由于论文需要,急需搭建Tensorflow环境,16年底当时Tensorflow版本号还没有过1,我曾按照手册搭建过CPU版本.目前,1.7算是比较新的版本了(也可以从源码编译1.8版本的Tens ...

  4. MySQL的常见存储引擎介绍与参数设置调优(转载)

    原文地址:http://www.cnblogs.com/demon89/p/8490229.html MySQL常用存储引擎之MyISAM 特性: 1.并发性与锁级别 2.表损坏修复 check ta ...

  5. Js的那些事

    先说说  var array = new Array(10); 和 var array = Array.apply(null, {length:10});这两个有啥区别,乍一看两个都是生成长度是10的 ...

  6. 在CentOs7上部署Gunicorn

    Gunicorn 的作用与优点这里就不再赘述,如不知道你也不会找这些对吧? 正文 安装简单,直接使用pip即可 pip3 install gunicorn 昨日在 Centos 中想部署Gunicor ...

  7. Python 爬虫 当当网图书 scrapy

    目标站点需求分析 获取当当网每个图书名字和评论数 涉及的库 scrapy,mysql 获取解析单页源码 保存到数据库中 结果

  8. Python知识目录

    目录 一.计算机基础 二.Python基础 三.函数 四.常用模块 五.模块和包 六.面向对象 七.网络编程socket 八.数据库 九.前端 十.Python Web框架 十一.版本控制--GIT ...

  9. RabbitMQ基础知识及Linux安装

    RabbitMQ: RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现. AMQP协议: AMQP,即Advanced Message Qu ...

  10. 如何把PDF文件拆分为多个文件

    一个PDF文件有很多个PDF页面组成,有时候我们只需要单个页面的时候应该怎么做呢,这个时候就需要拆分PDF文件了,那么如何把 PDF文件拆分为多个文件呢,应该有很多的小伙伴都想知道吧,那就让我们一起来 ...