第一次个人编程作业
作业所属课程 |
|
---|---|
作业要求 |
|
作业目标 |
设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。 |
我的 Github 链接:https://github.com/SmallGoldMedal/3122004499/tree/main
一、需求分析:
需求:
1.对输入的原文文件和抄袭版文件进行重复率分析计算;
2.使用命令行将重复率输出到答案文件内,其中数字精确到小数点后两位。
分析:
对于算法,可将源文件的句子和抄袭版文件的句子逐一比对,以计算重复率。具体而言:
1.在句句比较时,设定:句子内部重复率 = 重复字数与抄袭版文件被检测的句子总字数之比,当句子内部重复率 >= 50% 时,则认为句子涉嫌抄袭;
2.在文章比较时,设定:文章重复率 = 涉嫌抄袭句子数与抄袭版文件总句子数之比,计算结果即为重复率。
二、PSP2表格
Personal | Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 15 |
Estimate | 估计这个任务需要多少时间 | 1050 | 1150 |
Development | 开发 | 910 | 997 |
Analysis | 需求分析 (包括学习新技术) | 50 | 60 |
Design Spec | 生成设计文档 | 50 | 43 |
Design Review | 设计复审 | 20 | 20 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 20 | 15 |
Design | 具体设计 | 10 | 2 |
Coding | 具体编码 | 500 | 560 |
Code Review | 代码复审 | 20 | 20 |
Test | 测试(自我测试,修改代码,提交修改) | 300 | 340 |
Reporting | 报告 | 20 | 30 |
Test Repor | 测试报告 | 20 | 10 |
Size Measurement | 计算工作量 | 20 | 5 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 1050 | 1150 |
计算模块接口的设计与实现:
分为三个类:Main,readFile,putFile,其中:
- Main 类仅含main函数,引用 readFile() 方法和 putFile() 负责计算重复率;
- ReadFile类有 readFile() 方法,负责读入源文件和抄袭版文件;
- PutFile 类有 putFile() 方法,负责输出答案文件。
关系图:
文本的切割
public String[] getSentences() {
try {
String content = new String(Files.readAllBytes(Paths.get(fileName)));
//以“。”或换行符为标志对文章进行切割
return content.split("[。\\n]");
} catch (IOException e) {
//出错处理
System.err.println("读取文件错误: " + fileName);
e.printStackTrace();
return new String[0];
}
}
数据的输出
public static void putContent(String fileName, String content) {
try {
Files.write(Paths.get(fileName), content.getBytes());
} catch (IOException e) {
//出错处理
System.err.println("写入文件出错: " + fileName);
e.printStackTrace();
}
数据处理
int sCount = 0;
for (String pSentence : Sentences2) {
for (String oSentence : Sentences1) {
int sameWords = 0;
String[] pWords = pSentence.split("\\s+");
String[] oWords = oSentence.split("\\s+");
for (String pWord : pWords) {
for (String oWord : oWords) {
if (pWord.equals(oWord)) {
sameWords++;
break;
}
}
}
double similarity = (double) sameWords / pWords.length;
if (similarity >= 0.5) {
sCount++;
break;
}
}
}
计算模块接口部分的性能:
计算模块部分单元测试展示:
测试输入不同文件下的重复率:
测试代码
public class Test {
public static void main(String[] args) {
String test1= "src/main/resources/orig.txt";
String test2= "src/main/resources/orig_0.8_add.txt";
String test3= "src/main/resources/orig_0.8_del.txt";
String test4= "src/main/resources/orig_0.8_dis_1.txt";
String test5= "src/main/resources/orig_0.8_dis_10.txt";
String test6= "src/main/resources/orig_0.8_dis_15.txt";
String test7= "src/main/resources/test_1.txt";
String ans1="src/main/resources/ans.txt";
System.out.println("Test1:");
test(test1,test2,ans1);
System.out.println("Test2:");
test(test1,test3,ans1);
System.out.println("Test3:");
test(test1,test4,ans1);
System.out.println("Test4:");
test(test1,test5,ans1);
System.out.println("Test5:");
test(test1,test6,ans1);
System.out.println("Test6:");
test(test1,test7,ans1);
}
public static void test(String path1, String path2, String path3) {
//传入ReadFile以分解文本
ReadFile File1 = new ReadFile(path1);
ReadFile File2 = new ReadFile(path2);
String[] Sentences1 = File1.getSentences();
String[] Sentences2 = File2.getSentences();
//空文本报错
if (Sentences1.length == 0 || Sentences2.length == 0) {
System.out.println("文档有误或路径有误。");
return;
}
//进行统计
int sCount = 0;
for (String pSentence : Sentences2) {
for (String oSentence : Sentences1) {
int sameWords = 0;
String[] pWords = pSentence.split("\\s+");
String[] oWords = oSentence.split("\\s+");
for (String pWord : pWords) {
for (String oWord : oWords) {
if (pWord.equals(oWord)) {
sameWords++;
break;
}
}
}
double similarity = (double) sameWords / pWords.length;
if (similarity >= 0.5) {
sCount++;
break;
}
}
}
double pRate = (double) sCount / Sentences2.length * 100;
String result = String.format("%.2f%%", pRate);
//输出重复率
PutFile.putContent(path3, result);
System.out.println(result);
}
}
结果:
计算模块部分异常处理说明:
1.空文本报错
if (Sentences1.length == 0 || Sentences2.length == 0) {
System.out.println("文档有误或路径有误。");
return;
}
2.输入出错
System.err.println("读取文件错误: " + fileName);
e.printStackTrace();
return new String[0];
3.输出出错
System.err.println("写入文件出错: " + fileName);
e.printStackTrace();