第一次个人编程作业
作业要求
这个作业属于哪个课程 | 软件工程 |
---|---|
这个作业要求在哪里 | 个人项目 |
这个作业的目标 | 完成个人编程作业编码部分,学会如何进行编程、测试、性能分析等来完成一个初步软件,熟悉掌握github的使用 |
个人GitHub地址
PSP表
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 25 |
Estimate | 估计这个任务需要多少时间 | 100 | 150 |
Development | 开发 | 120 | 100 |
Analysis | 需求分析 (包括学习新技术) | 60 | 80 |
Design Spec | 生成设计文档 | 30 | 30 |
Design Review | 设计复审 | 15 | 10 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 12 |
Design | 具体设计 | 10 | 15 |
Coding | 具体编码 | 100 | 90 |
Code Review | 代码复审 | 15 | 10 |
Test | 测试(自我测试,修改代码,提交修改) | 20 | 20 |
Reporting | 报告 | 10 | 10 |
Test Repor | 测试报告 | 10 | 10 |
Size Measurement | 计算工作量 | 10 | 12 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 10 | 16 |
合计 | 540 | 590 |
需求分析
题目:论文查重
描述如下:
设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。
原文示例:今天是星期天,天气晴,今天晚上我要去看电影。
抄袭版示例:今天是周天,天气晴朗,我晚上要去看电影。
要求输入输出采用文件输入输出,规范如下:
从命令行参数给出:论文原文的文件的绝对路径。
从命令行参数给出:抄袭版论文的文件的绝对路径。
从命令行参数给出:输出的答案文件的绝对路径。
我们提供一份样例,课堂上下发,上传到班级群,使用方法是:orig.txt是原文,其他orig_add.txt等均为抄袭版论文。
注意:答案文件中输出的答案为浮点型,精确到小数点后两位
开发环境
编程语言:Java 17
IDE:Intellij IDEA 2023.1
性能分析工具:JProfiler 14.0
计算模块接口的设计与实现过程
- 设计流程图
2. 类和函数设计
类:
函数:
函数名 | 作用 | 所属的类 |
---|---|---|
readText | 用字符流文件读取文本并保存在字符串中 | PaperCheck |
writeText | 写入结果文本函数 | PaperCheck |
getSimilarityRatio | 计算相似度 | PaperCheck |
计算模块接口部分的性能改进
从这里可以看出首先最多调用的是int数组,因为SimHash算法的底层需要调用大量的int数组作为容器分装文章的句子,主要都是用于SimHash算法的分词和计算调用的
因此不需要更多改进。
程序中消耗最大的函数:
public static float getSimilarityRatio(String str, String target) {
// 矩阵
int[][] d;
int n = str.length();
int m = target.length();
// 遍历str的
int i;
// 遍历target的
int j;
// str的
char ch1;
// target的
char ch2;
// 记录相同字符,在某个矩阵位置值的增量,不是0就是1
int temp;
if (n == 0 || m == 0) {
return 0;
}
d = new int[n + 1][m + 1];
// 初始化第一列
for (i = 0; i <= n; i++) {
d[i][0] = i;
}
// 初始化第一行
for (j = 0; j <= m; j++) {
d[0][j] = j;
}
// 遍历str
for (i = 1; i <= n; i++) {
ch1 = str.charAt(i - 1);
// 去匹配target
for (j = 1; j <= m; j++) {
ch2 = target.charAt(j - 1);
if (ch1 == ch2 || ch1 == ch2 + 32 || ch1 + 32 == ch2) {
temp = 0;
} else {
temp = 1;
}
// 左边+1,上边+1, 左上角+temp取最小
d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1), d[i - 1][j - 1] + temp);
}
}
System.out.println("差异步骤:" + d[n][m]);
float similarity = 1 - (float) d[n][m] / Math.max(str.length(), target.length());
System.out.println("相似度:" + similarity);
return (1 - (float) d[n][m] / Math.max(str.length(), target.length())) * 100F;
} //计算相似度
计算模块部分单元测试展示
部分代码:
测试思路:
分别测试两个相同文件和两个不同文件
测试输入:
测试结果:
代码覆盖率: