软工第二次作业

一、作业概述

这个作业属于哪个课程 软件工程
这个作业要求在哪里 作业要求
这个作业的目标 实现论文查重功能,并进行代码测试

二、Github链接

Github

三、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 20 30
Estimate 估计这个任务需要多少时间 640 900
Development 开发 200 230
Analysis 需求分析 (包括学习新技术) 70 60
Design Spec 生成设计文档 30 35
Design Review 设计复审 30 40
Coding Standard 代码规范 (为目前的开发制定合适的规范) 20 30
Design 具体设计 100 120
Coding 具体编码 80 80
Code Review 代码复审 60 70
Test 测试(自我测试,修改代码,提交修改) 40 80
Reporting 报告 80 80
Test Repor 测试报告 45 60
Size Measurement 计算工作量 25 35
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30 30
合计 1470 1880

四、计算模块接口的设计与实现过程

4.1流程图

4.2类

MainPaperCheck: main方法所在类
HammingUtils: 计算海明距离的类
SimhashUtils: 计算Simhash值的类
ShortStringException: 处理文本内容过短的异常类

4.3关键代码

SimHash模块

分词

List<String> keywordList = HanLP.extractKeyword(str, str.length());

获取hash值

for(String keyword : keywordList){
            // 2、获取hash值
            String keywordHash = getHash(keyword);
            if (keywordHash.length() < 128) {
                // hash值可能少于128位,在低位以0补齐
                int dif = 128 - keywordHash.length();
                for (int j = 0; j < dif; j++) {
                    keywordHash += "0";
                }
            }

加权并合并

for (int j = 0; j < v.length; j++) {
                // 对keywordHash的每一位与'1'进行比较
                if (keywordHash.charAt(j) == '1') {
                    //权重分10级,由词频从高到低,取权重10~0
                    v[j] += (10 - (i / (size / 10)));
                } else {
                    v[j] -= (10 - (i / (size / 10)));
                }
            }
            i++;
        }

降维

String simHash = "";// 储存返回的simHash值
for (int j = 0; j < v.length; j++) {
    // 从高位遍历到低位
    if (v[j] <= 0) {
        simHash += "0";
    } else {
        simHash += "1";
    }
}

海明距离模块

getHammingDistance:用于将输入的两个simHash值计算其海明距离

for (int i = 0; i < simHash1.length(); i++) {
    // 每一位进行比较
    if (simHash1.charAt(i) != simHash2.charAt(i)) {
        distance++;
    }
}

getSimilarity:通过上述计算出的海明距离来计算相似度

return 0.01 * (100 - distance * 100 / 128);

五、性能分析

总览:

实时内存:

由图可以看出Java.lang.Float占用的内存最多,其中调用最多的是com.hankcs.hanlp包提供的接口,通过该方式来进行论文查重的话相对来说难以继续改进了。

六、单元测试

读写txt文件模块测试

public class TxtIOUtilsTest {
    @Test
    public void readTxtTest() {
        // 路径存在,正常读取
        String str = TxtIOUtils.readTxt("D:/test/orig.txt");
        String[] strings = str.split(" ");
        for (String string : strings) {
            System.out.println(string);
        }
    }
    @Test
    public void writeTxtTest() {
        // 路径存在,正常写入
        double[] elem = {0.11, 0.22, 0.33, 0.44, 0.55};
        for (int i = 0; i < elem.length; i++) {
            TxtIOUtils.writeTxt(elem[i], "D:/test/ans.txt");
        }
    }
    @Test
    public void readTxtFailTest() {
        // 路径不存在,读取失败
        String str = TxtIOUtils.readTxt("D:/test/none.txt");
    }
    @Test
    public void writeTxtFailTest() {
        // 路径错误,写入失败
        double[] elem = {0.11, 0.22, 0.33, 0.44, 0.55};
        for (int i = 0; i < elem.length; i++) {
            TxtIOUtils.writeTxt(elem[i], "User:/test/ans.txt");
        }
    }
}

测试结果

SimHash模块测试

public class SimHashUtilsTest {
    @Test
    public void getHashTest(){
        String[] strings = {"李明", "是", "一名", "优秀", "的", "工程师"};
        for (String string : strings) {
            String stringHash = SimHashUtils.getHash(string);
            System.out.println(stringHash.length());
            System.out.println(stringHash);
        }
    }
    @Test
    public void getSimHashTest(){
        String str0 = TxtIOUtils.readTxt("D:/test/orig.txt");
        String str1 = TxtIOUtils.readTxt("D:/test/orig_0.8_add.txt");
        System.out.println(SimHashUtils.getSimHash(str0));
        System.out.println(SimHashUtils.getSimHash(str1));
    }
}

测试结果

海明距离模块测试

public class HammingUtilsTest {
    @Test
    public void getHammingDistanceTest() {
        String str0 = TxtIOUtils.readTxt("D:/test/orig.txt");
        String str1 = TxtIOUtils.readTxt("D:/test/orig_0.8_add.txt");
        int distance = HammingUtils.getHammingDistance(SimHashUtils.getSimHash(str0), SimHashUtils.getSimHash(str1));
        System.out.println("海明距离:" + distance);
        System.out.println("相似度: " + (100 - distance * 100 / 128) + "%");
    }
}

测试结果

主测试

public class MainTest {
    @Test
    public void origAndAllTest(){
        String[] str = new String[6];
        str[0] = TxtIOUtils.readTxt("D:/test/orig.txt");
        str[1] = TxtIOUtils.readTxt("D:/test/orig_0.8_add.txt");
        str[2] = TxtIOUtils.readTxt("D:/test/orig_0.8_del.txt");
        str[3] = TxtIOUtils.readTxt("D:/test/orig_0.8_dis_1.txt");
        str[4] = TxtIOUtils.readTxt("D:/test/orig_0.8_dis_10.txt");
        str[5] = TxtIOUtils.readTxt("D:/test/orig_0.8_dis_15.txt");
        String ansFileName = "D:/test/ansAll.txt";
        for(int i = 0; i <= 5; i++){
            double ans = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str[0]), SimHashUtils.getSimHash(str[i]));
            TxtIOUtils.writeTxt(ans, ansFileName);
        }
    }
}

测试结果

结果如下:

七、异常处理

对于一些过短的文本,HanLp会无法取得关键字,这是需要进行异常处理

        try{
            if(str.length() < 200) throw new ShortStringException("文本过短!");
        }catch (ShortStringException e){
            e.printStackTrace();
            return null;
        }

这里实现了一个类,用于处理该异常。

public ShortStringException(String message) {
        super(message);
    }
posted @ 2023-09-08 00:21  frontier512  阅读(70)  评论(0)    收藏  举报