软件工程第一次个人编程作业

梁萍 2022-09-21 23:51:13
作业要求https://bbs.csdn.net/topics/608092799
GitHub仓库地址https://gitcode.net/qinchaofusu/3220004910

目录

  • 一、PSP表格
  • 二、设计
  • 2.1流程
  • 2.2类
  • 2.3核心算法(SimHash)
  • 三、接口设计和实现
  • 3.1 读写文件模块
  • 3.2 SimHashUtils模块
  • 3.3海明距离模块
  • 四、单元测试及结果展示
  • 五、代码质量和程序性能分析

一、PSP表格

PSP2.1Personal Sofware Process Stages预计耗时(分钟)实际耗时(分钟)
Planning计划3025
Estimate估计这个任务要多少时间1013
Development开发270330
Analysis需求分析(包括学习新技术)120150
Design Spec生成设计文档3035
Design Review设计复审2030
Coding Standard代码规范(为目前的开发制定合适的规范)2030
Design具体设计4045
Coding具体编码240350
Code Review代码复审3040
Test测试(自我测试,修改代码,提交修改)6070
Reporting报告9080
Test Repor测试报告3030
Size Measurement计算工作量2010
Postmortem & Process Plan事后总结(并提出过程改进计划)2015
合计10301253

二、设计

2.1流程

2.2类

MainPaperCheck:main 方法所在的类
HammingUtils:计算海明距离的类
SimHashUtils:计算 SimHash 值的类
readFileString:读 txt 文件的工具类
writeFileString:写 txt 文件的工具类

2.3核心算法(SimHash)

1、分词,把需要判断文本分词形成这个文章的特征单词。最后形成去掉噪音词的单词序列并为每个词加上权重,我们假设权重分为5个级别(1~5)。比如:“ 美国“51区”雇员称内部有9架飞碟,曾看见灰色外星人 ” ==> 分词后为 “ 美国(4) 51区(5) 雇员(3) 称(1) 内部(2) 有(1) 9架(3) 飞碟(5) 曾(1) 看见(3) 灰色(4) 外星人(5)”,括号里是代表单词在整个句子里重要程度,数字越大越重要。

2、hash,通过hash算法把每个词变成hash值,比如“美国”通过hash算法计算为 100101,“51区”通过hash算法计算为 101011。这样我们的字符串就变成了一串串数字,还记得文章开头说过的吗,要把文章变为数字计算才能提高相似度计算性能,现在是降维过程进行时。

3、加权,通过 2步骤的hash生成结果,需要按照单词的权重形成加权数字串,比如“美国”的hash值为“100101”,通过加权计算为“4 -4 -4 4 -4 4”;“51区”的hash值为“101011”,通过加权计算为 “ 5 -5 5 -5 5 5”。

4、合并,把上面各个单词算出来的序列值累加,变成只有一个序列串。比如 “美国”的 “4 -4 -4 4 -4 4”,“51区”的 “ 5 -5 5 -5 5 5”, 把每一位进行累加, “4+5 -4+-5 -4+5 4+-5 -4+5 4+5” ==》 “9 -9 1 -1 1 9”。这里作为示例只算了两个单词的,真实计算需要把所有单词的序列串累加。

5、降维,把4步算出来的 “9 -9 1 -1 1 9” 变成 0 1 串,形成我们最终的simhash签名。 如果每一位大于0 记为 1,小于0 记为 0。最后算出结果为:“1 0 1 0 1 1”。算法

三、接口设计和实现

3.1 读写文件模块

readFileString类:读取文件
writeFileString类:写入文件

3.2 SimHashUtils模块

包含了两个静态方法:
1、getHash:传入String,计算出它的hash值,并以字符串形式输出,(使用了MD5获得hash值)
2、getSimHash:传入String,计算出它的simHash值,并以字符串形式输出,(需要调用 getHash 方法)
主要代码如下(ps:使用了外部依赖 hankcs 包提供的接口进行分词)

 
        public static String getHash(String str) {        //这个类是为了获得hash值
            try {
                MessageDigest messageDigest = MessageDigest.getInstance("MD5");          // 使用了MD5
                return new BigInteger(1, messageDigest.digest(str.getBytes("UTF-8"))).toString(2);

            } catch (Exception e) {
                System.out.println("出错了。");
                return str;
            }
        }

        public static String getSimHash(String str) {
            List<String> keywordList = HanLP.extractKeyword(str, str.length());//取出所有关键词
            int size = keywordList.size();
            int i = 0;
            int[] v = new int[128];
            String simHash = "";// 储存返回的simHash值
            for (String keyword : keywordList) {
                String keywordHash = getHash(keyword);   //取hash值
                if (keywordHash.length() < 128) {
                    int a = 128 - keywordHash.length();
                    for (int j = 0; j < a; 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++;
            }
            //降维
            for (int j = 0; j < v.length; j++) {
                    // 从高位遍历到低位
                    if (v[j] <= 0) {
                        simHash += "0";
                    } else {
                        simHash += "1";
                    }
                }

            return simHash;
        }
    }

3.3海明距离模块

HammingUtils
包含了两个静态方法:

1、getHammingDistance:输入两个 simHash 值,计算出它们的海明距离 distance

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

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


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

##主类模块
1.从命令行输入两个文件名
2.计算两个文件的SimHash值
3.根据SimHash值计算出相似度
4.将结果存到一个文件中
5.结束程序

四、单元测试及结果展示

分别测试了读写文件模块,HammingUtils模块和SimHashUtils模块

img

主要模块的部分测试代码

public static void main(String[] args) {

        String[] strings = {"今天", "的", "天气", "真好", "呀"};
        for (String string : strings) {
            String stringHash = SimHashUtils.getHash(string);
            System.out.println(stringHash.length());
            System.out.println(stringHash);
        }

        String str0 = readFileString.readTxt("e:/orig.txt");
        String str1 = readFileString.readTxt("e:/orig_0.8_add.txt");
        System.out.println(SimHashUtils.getSimHash(str0));
        System.out.println(SimHashUtils.getSimHash(str1));


    }

结果展示

img

img

img

img

img

五、代码质量和程序性能分析

overview

img

方法调用情况

img

#六、异常处理
判断输出结果的文件路径是否存在


 try {
            if(file.exists()){
                //判断文件是否存在,如果不存在就新建一个txt
                file.createNewFile();
            }
            fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(content.getBytes());
            fileOutputStream.flush();
            fileOutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
...全文
126 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
梁萍 2022-09-23
  • 打赏
  • 举报
回复

实在是登不上github网站,把代码文件传到gitcode上了

203

社区成员

发帖
与我相关
我的任务
社区描述
高校教学社区
其他 高校 广东省·广州市
社区管理员
  • ryue.zh
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧