BUAA SE 个人项目作业
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 2020春季计算机学院软件工程(罗杰 任健) |
| 这个作业的要求在哪里 | 个人项目作业 |
| 我在这个课程的目标是 | 通过个人项目实践熟悉个人开发流程 |
一、在文章开头给出教学班级和可克隆的 Github 项目地址
- 教学班级:005
- 项目地址:https://github.com/NoSameRain/BUAA_SE_IntersectPrj
二、在开始实现程序之前,在下述 PSP 表格记录下你估计将在程序的各个模块的开发上耗费的时间。
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | ||
| · Estimate | · 估计这个任务需要多少时间 | 10 | 10 |
| Development | 开发 | ||
| · Analysis | · 需求分析 (包括学习新技术) | 60 | 90 |
| · Design Spec | · 生成设计文档 | 30 | 30 |
| · Design Review | · 设计复审 (和同事审核设计文档) | 15 | 10 |
| · Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
| · Design | · 具体设计 | 90 | 120 |
| · Coding | · 具体编码 | 100 | 120 |
| · Code Review | · 代码复审 | 60 | 60 |
| · Test | · 测试(自我测试,修改代码,提交修改) | 120 | 170 |
| Reporting | 报告 | ||
| · Test Report | · 测试报告 | 30 | 30 |
| · Size Measurement | · 计算工作量 | 30 | 30 |
| · Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 60 | 80 |
| 合计 | 615 | 760 |
三、解题思路描述。即刚开始拿到题目后,如何思考,如何找资料的过程。
1. 题目要求
给定 N 条直线,询问平面中有多少个点在至少 2 条给定的直线上。题目输入保证答案只有有限个。
输入格式
- 第 1 行:一个自然数 N >= 1,表示输入的直线的数目。注:具体的 N 的限制参见评分规则。
- 第 2 行至第 N + 1 行:每行描述一条直线。具体格式如下:
- 直线:L ,表示通过点 (x1, y1) 和 (x2, y2) 的直线。输入保证给定两点不重合。
所有直线参数均为整数,范围为 (-100000, 100000)。
输出格式
共 1 行,输出平面中满足需求的点的数目。
2. 解题思路
对于任意两条直线,位置关系有两种情况:相交、平行(重合),即交点个数可能为:1个、0个。
在最初看到题目时,我的思路是将任意两条直线的交点求出并保存,最后记录交点个数。对于N=1的情况直接判定交点个数为0。对于N>1的情况,先判断两条直线是否平行,若平行则转而对其他直线进行判断,否则求出这两条直线的交点坐标,确定这个交点坐标之前没有出现过后再保存它。
这次题目我在保存直线的什么信息上思考了稍久,主要还是根据要利用什么方法求交点坐标来决定。这次我利用了“已知两条直线四个点的坐标,根据四个坐标值直接求交点坐标”的方法,可参见下面这个博客。
两点确定一条直线,已知四个点确定的两条直线,求这两条直线的交点
求坐标方法和具体公式确定了,相应的数据结构也就能确定了。由于这个公式中用到的数据只涉及坐标值,所以我在直线的类中就存储了这个直线的x1 y1 x2 y2的值,以及斜率k值,以方便之后判断两条直线的位置关系(平行、相交)。
由于一个假期没写代码有些生疏,所以复习c++的vector、map容器等知识也花费了一部分时间。
四、设计实现过程。设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?单元测试是怎么设计的?
我的代码只设置了line类用于存储直线的相关信息。函数只有4个。分别用来对输入值进行处理、存储直线信息、判断所有直线中任意两条直线的位置关系、计算交点坐标并进行存储。我这次代码写的比较面向过程,基本在main函数里一个个调用了其余几个有特定功能的函数。由于结构和函数功能都比较简单所以不需要流程图。单元由于这次要实现的功能不是特别复杂所以单元测试颗粒粒度较大。基本是针对整个大功能进行测试(即直接测试最后输出的交点个数是否正确)没有对其中几个小功能进行测试。测试样例都是根据一些边界条件以及直线位置关系来设计的。比如输入的坐标值设为-9999、9999等这样的值,以及令所有直线都平行、部分平行部分相交、所有直线都交于同一点、部分直线交于同一点部分直线不交于同一点等情况的组合。由于分析覆盖率的插件一直无法下载所以未分析覆盖率。

五、记录在改进程序性能上所花费的时间,描述你改进的思路,并展示一张性能分析图(由 VS 2019 的性能分析工具自动生成),并展示你程序中消耗最大的函数。
改进性能起码花费了3个小时。主要涉及给交点去重的部分。最开始我是将计算出的交点坐标存储在一个二维数组中,每次存储之前先通过遍历数组查找这一交点是否与数组中的交点重复。但这个方法由于性能太差直接被我pass掉了(后来反思应该是遍历这里做的不够好,导致N大于1000时直接爆掉)

后来想到map键值的唯一性,就想利用这个特性来代替遍历去重的工作,于是改用map来存储所有交点坐标。实施后性能改善了很多。但可以看出map所带来的消耗还是很大的。以及我在这里为了将x、y坐标作为键值存储用了一个很奇怪,或者说不太符合规范?的方法。我将x、y全都转换为string类型并连接了起来。这里可以看到to_string也带来了相当大的消耗。但这里我还是不能很好解决。导致其所在的函数消耗也很大。(这里写了一个用于测试性能的代码,主要是随机生成1000个x、y坐标值在-10000到10000之间的字符串。)


以及这里再补充一下code quality analysis情况,刚开始涉及一些变量未赋初始值的问题,后来都改掉了

六、代码说明。展示出项目关键代码,并解释思路与注释说明。
1.类说明
class line
{
public:
int x1 = 0;
int x2 = 0;
int y1 = 0;
int y2 = 0;
int x2_x1 = 0; //x2 - x1
int y2_y1 = 0; //y2 - y1
double k = 0;
bool ulimited = false; //无斜率;
void store_coor(string str);
};
可以看出这一部分主要就是对直线坐标和斜率进行存储,以方便之后的计算。
2. 函数说明
这个函数用来处理字符串并给相应的对象赋值
void line::store_coor(string str)
{
vector<string> res;//用于存放分割后的字符串
string result;//暂存从str中读取的字符串
stringstream input(str);//将字符串读到input中
while (input >> result)
res.push_back(result);//依次输出到result中,并存入res中
x1 = stoi(res[1], 0, 10);
y1 = stoi(res[2], 0, 10);
x2 = stoi(res[3], 0, 10);
y2 = stoi(res[4], 0, 10);;
x2_x1 = stoi(res[3], 0, 10) - stoi(res[1], 0, 10);
y2_y1 = stoi(res[4], 0, 10) - stoi(res[2], 0, 10);
if (x2_x1 == 0)
{
ulimited = true;
}
else
{
k = y2_y1 / x2_x1;
}
}
这一部分用来遍历所有的直线,判断其中两条直线的位置关系并计算交点坐标
void cnt_coor_num()
{
int i, j;
for (i = 0;i < N;i++)
for (j = i + 1;j < N;j++)
{
if (coor_4_line[i].ulimited == true || coor_4_line[j].ulimited == true)
{
if (coor_4_line[i].ulimited != coor_4_line[j].ulimited)
{
calcu_coor(i, j);
}
}
else
{
if (coor_4_line[i].k != coor_4_line[j].k)
{
calcu_coor(i, j);
}
}
}
}
这一部分用来计算两条直线的交点坐标。bug也主要是出现在这里。因为用坐标来直接计算有时候会涉及分子分母为0的情况,这一点我在最开始没有好好思考就急着写代码了,后来决定将分子分母为0的情况单列出来讨论(有时候涉及到分子分母同时消去0)这可能是直接用坐标值计算交点坐标这种方法的一个缺点。
现在再看真的是有点不堪入目。。。。虽然功能实现了,但是不够简洁优美
void calcu_coor(int i, int j)
{
string coor;
double x, y, xa;
int ya,yb,xb;
xa = 0;
ya = ((-coor_4_line[i].y2_y1) * (coor_4_line[j].y2_y1) * coor_4_line[i].x1 +
(coor_4_line[j].y2_y1) * (coor_4_line[i].x2_x1) * coor_4_line[i].y1 +
(coor_4_line[i].y2_y1) * (coor_4_line[j].y2_y1) * coor_4_line[j].x1 +
(-coor_4_line[j].x2_x1) * (coor_4_line[i].y2_y1) * coor_4_line[j].y1);
yb = coor_4_line[i].x2_x1 * coor_4_line[j].y2_y1 + (-coor_4_line[i].y2_y1) * coor_4_line[j].x2_x1;
if (ya == 0)
{
if (yb == 0) y = 1;
else y = 0;
}
else y = ya / yb;
int m = j;
if (coor_4_line[j].k == 0) {
m = i;
}
xb = -coor_4_line[m].y2_y1;
if (xb == 0)
{
if (coor_4_line[m].x2_x1 == 0) xa = y - coor_4_line[m].y2;
else if ((y - coor_4_line[m].y2) == 0) xa = -coor_4_line[m].x2_x1;
}
else xa = -coor_4_line[m].x2_x1 * (y - coor_4_line[m].y2) / xb;
x = coor_4_line[m].x2 + xa;
coor = to_string(x) + to_string(y); //shit
intersection.insert(pair<string, int>(coor, 0));
//duplicate_remove(x, y);
}
七、在你实现完程序之后,在下述 PSP 表格记录下你在程序的各个模块上实际花费的时间。
见上面的表格。可以看到实际花费的时间还是比预期多很多。主要是后面进行单元测试、改进性能、修改代码花费了很多时间。
BUAA SE 个人项目作业的更多相关文章
- BUAA软件工程个人项目作业
BUAA软件工程个人项目作业 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 我在这个课程的目标是 学习软件开发的流程 这个作业在哪 ...
- BUAA软件工程结对项目作业
BUAA软件工程结对项目 小组成员:16005001,17373192 1.教学班级和项目地址 项目 内容 这个作业属于哪个课程 博客园班级连接 这个作业的要求在哪里 结对项目作业 我在这个课程的目标 ...
- 【BUAA 软工个人项目作业】玩转平面几何
BUAA 软件工程个人项目作业 项目 内容 课程:2020春季软件工程课程博客作业(罗杰,任健) 博客园班级链接 作业:BUAA软件工程个人项目作业 作业要求 课程目标 学习大规模软件开发的技巧与方法 ...
- BUAA 2020 软件工程 个人项目作业
BUAA 2020 软件工程 个人项目作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 ...
- BUAA 软工 结对项目作业
1.相关信息 Q A 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 结对项目作业 我在这个课程的目标是 系统地学习软件工程开发知识,掌握相关流程和技术,提升 ...
- BUAA软工-结对项目作业
结对项目作业 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 结对项目作业 我在这个课程的目标是 通过这门课锻炼软件开发能力和经验,强化与他人合作 ...
- BUAA 2020 软件工程 结对项目作业
Author: 17373051 郭骏 3.28添加:4.计算模块接口的设计与实现过程部分,PairCore实现的细节 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) ...
- BUAA软件工程个人项目
写在前面 项目 内容 所属课程 2020春季计算机学院软件工程(罗杰 任健) (北航) 作业要求 [个人项目作业](<https://edu.cnblogs.com/campus/buaa/BU ...
- BUAA 2020 软件工程 热身作业
BUAA 2020 软件工程 热身作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 第一次作业-热身! ...
随机推荐
- C# Dapper基本三层架构使用 (三、BLL)
BLL层介绍 业务逻辑层用于做一些有效性验证的工作,以更好的保证程序运行的健壮性.如完成数据添加.修改和查询业务等:不允许指定的文本框中输入空字符串,数据格式是否正确以及数据类型验证:用户权限的合法性 ...
- DataTable 增加、修改、删除
using System; using System.Data; using System.Windows.Forms; using DotNet.Utilities; namespace Windo ...
- angularjs实现购物清单
HTML: 1:要定义ng-app,在html上定义ng-app="App"; 2:在body上定义ng-controller="ToDoCtrl" 3: &l ...
- 自定义-starter
目录 说明 编写启动器 新建项目测试我们自己写的启动器 分析完毕了源码以及自动装配的过程,可以尝试自定义一个启动器来玩玩! 自动装配的过程 SpringBoot-静态资源加载-源码 SpringBoo ...
- (3)java Spring Cloud+Spring boot+mybatis企业快速开发架构之SpringCloud-Spring Cloud和Dubbo的区别及各自的优缺点
我们先从 Nginx 说起,了解为什么需要微服务.最初的服务化解决方案是给相同服务提供一个统一的域名,然后服务调用者向这个域发送 HTTP 请求,由 Nginx 负责请求的分发和跳转. 这种架构存 ...
- 【C++基础教程】第五课
上次的作业答案,非常简单. 第一题: 我们需要知道,字符(char类型)在计算机中存储的时候,是把这个字符对应的代码(专业术语叫做编码)进行存储.例如,换行符'\n'的代码就是10,'0'对应的代码就 ...
- 【简单数据结构】二叉树的建立和递归遍历--洛谷 P1305
题目描述 输入一串二叉树,用遍历前序打出. 输入格式 第一行为二叉树的节点数n.(n \leq 26n≤26) 后面n行,每一个字母为节点,后两个字母分别为其左右儿子. 空节点用*表示 输出格式 前序 ...
- httpd进程数统计,IP封禁,IP连接数量情况查看
ps -ef|grep httpd|wc -l 统计httpd进程数,连个请求会启动一个进程,使用于Apache服务器. 查看Apache的并发请求数及其TCP连接状态:netstat -n | aw ...
- ❤️【Android精进之路-03】创建第一个Android应用程序竟然如此简单❤️
您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. 本文会重点介绍如何创建第一个Android应用,以及如何使用Android Studio进行调试 干货满满,建议收藏,需要用到时常看看.小伙伴们如 ...
- win10系统显示此电脑
今天电脑开机后发现从任务栏进入"文件资源管理器",直接卡死,重启电脑也没有用. 我想到是不是从"此电脑"进入不会卡死,试了一下果真没有卡死. 使用win10系统 ...