第一个个人编程作业

 

一、作业基本信息

这个作业属于哪个课程

班级链接

这个作业要求在哪里

作业要求的链接

这个作业的目标

编写代码实现查重功能,学习使用PSP表格,学习commit规范

 


二、作业链接

链接:https://github.com/jamehhh012/work-3221005071.git

三、PSP表格

PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planing 计划 40 60
.Estimate .估计这个任务需要多久时间 10 10
Development 开发 300 120
.Analysis .需求分析(包括学习新技术) 120 30
.Design Review .设计复审 20 30
.Coding Standard .代码规范 10 10
.Design .具体设计 40 30
.Coding .具体编码 240 240
.Code Review .代码复审 60 30
.Test .测试 60 50
.Reporting .报告 90 120
.Test Report .测试报告 20 20
.Size Measurement .计算工作量 20 10
.Postmortem & Process Improvement Plan . 事后总结,并提出过程改进计划 60 70
  . 合计 1110 885

 

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

4.1 程序实现类

  • main_Check:main 方法所在的类
  • HammingUtils:计算海明距离的类
  • SimHashUtils:计算 SimHash 值的类
  • TxtIOUtils:读写 txt 文件的工具类
  • ShortStringException:处理文本内容过短的异常类

整体流程:

 

 

4.2接口的设计和实现

读写模块TxtIOUtils

包含了两个静态方法:

1、readTxt:读取txt文件

2、writeTxt:写入txt文件

SimHash模块

包含了两个静态方法:

1、getHash:传入String,计算出它的hash值,并以字符串形式输出,(使用了MD5获得hash值)

2、getSimHash:传入String,计算出它的simHash值,并以字符串形式输出,(需要调用 getHash 方法)

海明距离模块

包含了两个静态方法:

1、getHammingDistance:输入两个 simHash 值,计算出它们的海明距离 distance
2、getSimilarity:输入两个 simHash 值,调用 getHammingDistance 方法得出海明距离 distance,在由 distance 计算出相似度

4.3核心算法

SimHash+海明距离

  public static String getHash(String str){
        try{
            // 这里使用了MD5获得hash值
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            return new BigInteger(1, messageDigest.digest(str.getBytes("UTF-8"))).toString(2);
        }catch(Exception e){
            e.printStackTrace();
            return str;
        }
    }
 
    /**
     * 传入String,计算出它的simHash值,并以字符串形式输出
     * @param str 传入的Srting类型字符串
     * @return 返回str的simHash值
     */
    public static String getSimHash(String str){
        // 文本长度太短时HanLp无法取得关键字
        try{
            if(str.length() < 200) throw new ShortStringException("文本过短!");
        }catch (ShortStringException e){
            e.printStackTrace();
            return null;
        }
        // 用数组表示特征向量,取128位,从 0 1 2 位开始表示从高位到低位
        int[] v = new int[128];
        // 1、分词(使用了外部依赖hankcs包提供的接口)
        List<String> keywordList = HanLP.extractKeyword(str, str.length());//取出所有关键词
        // hash
        int size = keywordList.size();
        int i = 0;//以i做外层循环
        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";
                }
            }
            // 3、加权、合并
            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++;
        }
        // 4、降维
        String simHash = "";// 储存返回的simHash值
        for (int j = 0; j < v.length; j++) {
            // 从高位遍历到低位
            if (v[j] <= 0) {
                simHash += "0";
            } else {
                simHash += "1";
            }
        }
        return simHash;
    }
}

  

 
public class HammingUtils {
    /**
     * 输入两个simHash值,计算它们的海明距离
     * @param simHash1
     * @param simHash2
     * @return 海明距离
     */
    public static int getHammingDistance(String simHash1, String simHash2) {
        int distance = 0;
        if (simHash1.length() != simHash2.length()) {
            // 出错,返回-1
            distance = -1;
        } else {
            for (int i = 0; i < simHash1.length(); i++) {
                // 每一位进行比较
                if (simHash1.charAt(i) != simHash2.charAt(i)) {
                    distance++;
                }
            }
        }
        return distance;
    }
    /**
     * 输入两个simHash值,输出相似度
     * @param simHash1
     * @param simHash2
     * @return 相似度
     */
    public static double getSimilarity(String simHash1, String simHash2) {
        // 通过 simHash1 和 simHash2 获得它们的海明距离
        int distance = getHammingDistance(simHash1, simHash2);
        // 通过海明距离计算出相似度,并返回
        return 0.01 * (100 - distance * 100 / 128);
    }
}

  

五、单元测试

5.1 部分测试代码

     @Test
        public void getHammingDistanceTest() {
            String str0 = TxtIOUtils.readTxt("C:\\Users\\jame\\Desktop\\ruangong\\text\\orig.txt");
            String str1 = TxtIOUtils.readTxt("C:\\Users\\jame\\Desktop\\ruangong\\text\\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) + "%");
        }

  

    @Test
    public void origAndAllTest(){
        String[] str = new String[6];
        str[0] = TxtIOUtils.readTxt("C:\\Users\\jame\\Desktop\\ruangong\\text\\orig.txt");
        str[1] = TxtIOUtils.readTxt("C:\\Users\\jame\\Desktop\\ruangong\\text\\orig_0.8_add.txt");
        str[2] = TxtIOUtils.readTxt("C:\\Users\\jame\\Desktop\\ruangong\\text\\orig_0.8_del.txt");
        str[3] = TxtIOUtils.readTxt("C:\\Users\\jame\\Desktop\\ruangong\\text\\orig_0.8_dis_1.txt");
        str[4] = TxtIOUtils.readTxt("C:\\Users\\jame\\Desktop\\ruangong\\text\\orig_0.8_dis_10.txt");
        str[5] = TxtIOUtils.readTxt("C:\\Users\\jame\\Desktop\\ruangong\\text\\orig_0.8_dis_15.txt");
        String ansFileName = "C:\\Users\\jame\\Desktop\\ruangong\\text\\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);
        }
    }

  

5.2 测试结果

 

\

5.3 代码覆盖率

 

 

 

5.4 结果文件

 

 

 


 

六、性能分析

1、

 

 

2.

 

posted @ 2023-09-17 20:30  bhbhh  阅读(75)  评论(0)    收藏  举报