第一次个人编程作业
| 这个作业属于哪个课程 | 计科22级12班 |
|---|---|
| 这个作业要求在哪里 | 个人项目 |
| 这个作业的目标 | 尝试开发一个论文查重的项目,并进行单元测试 |
需求分析
题目:论文查重
描述如下:
设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。
- 原文示例:今天是星期天,天气晴,今天晚上我要去看电影。
- 抄袭版示例:今天是周天,天气晴朗,我晚上要去看电影。
要求输入输出采用文件输入输出,规范如下:
- 从命令行参数给出:论文原文的文件的绝对路径。
- 从命令行参数给出:抄袭版论文的文件的绝对路径。
- 从命令行参数给出:输出的答案文件的绝对路径。
我们提供一份样例,课堂上下发,上传到班级群,使用方法是:orig.txt是原文,其他orig_add.txt等均为抄袭版论文。
注意:答案文件中输出的答案为浮点型,精确到小数点后两位
PSP表格
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 10 | 10 |
| · Estimate | · 估计这个任务需要多少时间 | 10 | 10 |
| Development | 开发 | 760 | 821 |
| · Analysis | · 需求分析 (包括学习新技术) | 60 | 36 |
| · Design Spec | · 生成设计文档 | 60 | 40 |
| · Design Review | · 设计复审 | 20 | 10 |
| · Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 15 |
| · Design | · 具体设计 | 60 | 50 |
| · Coding | · 具体编码 | 300 | 360 |
| · Code Review | · 代码复审 | 30 | 30 |
| · Test | · 测试(自我测试,修改代码,提交修改) | 120 | 200 |
| Reporting | 报告 | 40 | 30 |
| · Test Repor | · 测试报告 | 20 | 20 |
| · Size Measurement | · 计算工作量 | 20 | 10 |
| · Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 20 |
| · 合计 | 770 | 831 |
接口的设计与实现
代码组织
- 项目结构

| 类 | 作用 |
|---|---|
| Main.java | 提供程序入口,调用其他类 |
| File_IO.java | 读写文件 |
| SimHash.java | 计算simHash值 |
| Hamming.java | 计算相似度 |
| ShortStringException.java | 文章过短时的异常处理 |
算法关键
该程序运用了SimHash算法,利用海明距离比较内容之间的相似度。SimHash是用来处理海量文本去重的算法。主要思想是降维,算出海明距离来确定文本的相似度,海明距离越小,相似度越低。
性能分析
总览

方法调用次数

单元测试展示
测试Main
点击查看代码
class MainTest {
/**
* 测试原文件和其他抄袭文件(包括自己)的相似度
*/
@Test
public void origAndOrigTest(){
String str0 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig.txt");
String str1 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig.txt");
String ansFileName = "D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\ansAndOrigTest.txt";
double ans = Hamming.getSimilarity(SimHash.getSimHash(str0), SimHash.getSimHash(str1));
System.out.println("查重率:"+ans*100+"%");
File_IO.writeFile(ans, ansFileName);
}
@Test
public void origAndAddTest(){
String str0 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig.txt");
String str1 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig_0.8_add.txt");
String ansFileName = "D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\ansAndAddTest.txt";
double ans =Hamming.getSimilarity(SimHash.getSimHash(str0), SimHash.getSimHash(str1));
System.out.println("查重率:"+ans*100+"%");
File_IO.writeFile(ans, ansFileName);
}
@Test
public void origAndDelTest(){
String str0 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig.txt");
String str1 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig_0.8_del.txt");
String ansFileName = "D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\ansAndDelTest.txt";
double ans = Hamming.getSimilarity(SimHash.getSimHash(str0), SimHash.getSimHash(str1));
System.out.println("查重率:"+ans*100+"%");
File_IO.writeFile(ans, ansFileName);
}
@Test
public void origAndDis1Test(){
String str0 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig.txt");
String str1 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig_0.8_dis_1.txt");
String ansFileName = "D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\ansAndDis1Test.txt";
double ans = Hamming.getSimilarity(SimHash.getSimHash(str0), SimHash.getSimHash(str1));
System.out.println("查重率:"+ans*100+"%");
File_IO.writeFile(ans, ansFileName);
}
@Test
public void origAndDis10Test(){
String str0 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig.txt");
String str1 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig_0.8_dis_10.txt");
String ansFileName = "D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\ansAndDis10Test.txt";
double ans = Hamming.getSimilarity(SimHash.getSimHash(str0), SimHash.getSimHash(str1));
System.out.println("查重率:"+ans*100+"%");
File_IO.writeFile(ans, ansFileName);
}
@Test
public void origAndDis15Test(){
String str0 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig.txt");
String str1 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig_0.8_dis_15.txt");
String ansFileName = "D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\ansAndDis15Test.txt";
double ans = Hamming.getSimilarity(SimHash.getSimHash(str0), SimHash.getSimHash(str1));
System.out.println("查重率:"+ans*100+"%");
File_IO.writeFile(ans,ansFileName);
}
}

测试读写文件File_IO
点击查看代码
class File_IOTest {
/**
* 正常读写情况
*/
@Test
void testReadFile() {
// 路径存在,正常读取
String str = readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig.txt");
String[] strings = str.split(" ");
for (String string : strings) {
System.out.println(string);
}
}
@Test
void testWriteTxt() {
// 路径存在,正常写入
double[] elem = {0.1, 0.2, 0.3, 0.4, 0.5};
for (int i = 0; i < elem.length; i++) {
writeFile(elem[i], "D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\ansAndOrigTest.txt");
}
}
/**
* 异常读情况
*/
@Test
public void readTxtFailTest() {
// 路径不存在,读取失败
String str = readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\nullTest.txt");
}
}

测试SimHash
点击查看代码
class SimHashTest {
/**
* 测试GetHash
*/
@Test
void testGetHash() {
String[] strings = {"你", "好", "GDUT", "我爱编程", "软件工程"};
for (String string : strings) {
String stringHash = SimHash.getHash(string);
System.out.println(stringHash.length());
System.out.println(stringHash);
}
}
/**
* 测试GetSimHash
*/
@Test
void testGetSimHash() {
String str0 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig.txt");
String str1 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig_0.8_add.txt");
System.out.println(SimHash.getSimHash(str0));
System.out.println(SimHash.getSimHash(str1));
}
}

测试Hamming
点击查看代码
class HammingTest {
/**
* 测试GetHammingDistance正常情况
*/
@Test
void testGetHammingDistance() {
String str0 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig.txt");
String str1 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig_0.8_add.txt");
int distance = Hamming.getHammingDistance(SimHash.getSimHash(str0), SimHash.getSimHash(str1));
System.out.println("海明距离:" + distance);
System.out.println("相似度: " + (100 - distance * 100 / 128) + "%");
}
/**
* 测试GetHammingDistance异常情况
*/
@Test
void testGetHammingDistanceFail() {
String str0 = "1010";
String str1 = "1111";
System.out.println(Hamming.getHammingDistance(str0, str1));
}
/**
* 测试GetSimilarity
*/
@Test
void testGetSimilarity() {
String str0 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig.txt");
String str1 = File_IO.readFile("D:\\LJun521\\3222004682\\论文查重\\src\\测试文本\\orig_0.8_add.txt");
int distance = Hamming.getHammingDistance(SimHash.getSimHash(str0), SimHash.getSimHash(str1));
double similarity = Hamming.getSimilarity(SimHash.getSimHash(str0), SimHash.getSimHash(str1));
System.out.println("str0和str1的海明距离: " + distance);
System.out.println("str0和str1的相似度:" + similarity);
}
}

代码覆盖率


浙公网安备 33010602011771号