当前位置: 首页 > news >正文

软件工程第一次编程作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience/homework/13477
这个作业的目标 实现一个3000字以上论文查重程序

github地址:https://github.com/ironlifes/3123004784


一、PSP表格如下

Process Stages Process Stages (中文) 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 20 15
· Estimate · 估计这个任务需要多少时间 190 240
Development 开发 200 180
· Analysis · 需求分析 (包括学习新技术) 120 120
· Design Spec · 生成设计文档 15 15
· Design Review · 设计复审 25 25
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 20 10
· Design · 具体设计 40 50
· Coding · 具体编码 50 70
· Code Review · 代码复审 30 55
· Test · 测试(自我测试,修改代码,提交修改) 20 30
Reporting 报告 70 90
· Test Report · 测试报告 40 50
· Size Measurement · 计算工作量 20 20
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 20 10
· 合计 880 980

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

1、程序整体结构

d:\java code\rjgc/
├── src/                 # 源代码目录
│   ├── Main.java        # 主程序入口和测试类
│   ├── PaperChecker.java    # 原始论文查重实现
│   ├── OptimizedPaperChecker.java # 优化版论文查重算法
│   └── PerformanceAnalyzer.java   # 性能分析工具类
├── out/                 # 编译输出目录
│   └── production/rjgc/ # 编译后的class文件
├── orig.txt             # 原始论文文本文件
├── orig_add.txt         # 抄袭版论文文本文件
├── ans.txt              # 查重结果输出文件
└── .idea/               # IntelliJ IDEA配置文件

2、程序流程图

graph TD%% 全局设置classDef user fill:#add8e6,stroke:#000000;classDef entry fill:#90ee90,stroke:#000000;classDef algorithm fill:#ffffcc,stroke:#000000;classDef performance fill:#ffb6c1,stroke:#000000;classDef data fill:#b0e0e6,stroke:#000000;classDef specificAlgorithm fill:#fffacd,stroke:#000000;%% 用户层subgraph "用户层" user[用户]:::userend%% 入口层subgraph "入口层" main["Main.java\n测试入口"]:::entrypaperCheckerMain["PaperChecker.java\n主程序入口"]:::entryend%% 算法层subgraph "算法层" paperChecker["PaperChecker.java\n基础算法实现"]:::algorithmoptimizedPaperChecker["OptimizedPaperChecker.java\n优化算法实现"]:::algorithm%% 具体算法cosineSimilarity["余弦相似度算法"]:::specificAlgorithmsimpleMatch["简单词频匹配算法"]:::specificAlgorithmjaccardSimilarity["Jaccard相似度算法"]:::specificAlgorithmsimHash["SimHash算法"]:::specificAlgorithmend%% 性能分析层subgraph "性能分析层" performanceAnalyzer["PerformanceAnalyzer.java\n性能分析工具"]:::performanceend%% 数据层subgraph "数据层" fileIO["文件读写操作"]:::datatokenization["文本分词处理"]:::datatfCalculation["词频计算"]:::dataend%% 连接关系 - 用户交互user -->|运行主程序| paperCheckerMainuser -->|运行测试| main%% 主程序流程paperCheckerMain -->|读取文件| fileIOpaperCheckerMain -->|调用算法| paperCheckerpaperCheckerMain -->|写入结果| fileIOpaperCheckerMain -->|记录性能| performanceAnalyzer%% 测试流程main -->|测试基础算法| paperCheckermain -->|测试优化算法| optimizedPaperCheckermain -->|记录测试性能| performanceAnalyzer%% 算法调用关系paperChecker -->|默认算法| cosineSimilaritypaperChecker -->|可选算法| simpleMatchpaperChecker -->|可选算法| jaccardSimilaritypaperChecker -->|分词| tokenizationpaperChecker -->|计算词频| tfCalculationoptimizedPaperChecker -->|优化版本| cosineSimilarityoptimizedPaperChecker -->|新增算法| simHashoptimizedPaperChecker -->|优化分词| tokenizationoptimizedPaperChecker -->|优化词频计算| tfCalculation%% 性能分析调用paperChecker -->|性能监控| performanceAnalyzeroptimizedPaperChecker -->|性能监控| performanceAnalyzer%% 辅助流程cosineSimilarity -->|使用词频| tfCalculation%% 图例说明legend["图例说明:"]legend --> legend1["→ 数据流向"]legend --> legend2[":::user 用户层"]legend --> legend3[":::entry 入口层"]legend --> legend4[":::algorithm 算法层"]legend --> legend5[":::performance 性能分析层"]legend --> legend6[":::data 数据层"]

3、算法关键与独到之处

3.1 余弦相似度算法

  • 核心思想:将文本转换为向量空间中的向量,计算两个向量之间的夹角余弦值
  • 实现步骤:文本分词 → 计算词频 → 构建向量 → 计算余弦值
  • 独到之处:考虑了词频因素,对于较长文本有较好的区分度

3.2 SimHash算法

  • 核心思想:将高维特征向量压缩为低维指纹,通过汉明距离衡量相似度
  • 实现步骤:文本分词 → 计算每个词的哈希值 → 更新向量 → 生成最终哈希值
  • 独到之处:适用于大规模文本比较,计算效率高,空间占用小

三、计算模块接口部分的性能改进

1、性能改进思路

1.1 分词算法优化

  • 将正则表达式分词改为字符遍历分词
  • 对于中文文本,采用更高效的二元语法分词策略
  • 使用StringBuilder代替字符串拼接操作

1.2 词频计算优化

  • 预分配HashMap容量,减少扩容开销
  • 使用compute方法替代getOrDefault+put操作

1.3 余弦相似度计算优化

  • 选择较小的集合进行迭代,减少循环次数
  • 预先计算向量模长,避免重复计算

1.4 新增SimHash算法

  • 针对大文本比较场景,提供更高效的相似度计算方法
  • 使用位运算优化哈希值计算过程

2、性能分析图

image

3、性能对比数据

操作 原始算法耗时(ms) 优化算法耗时(ms) 性能提升
文件读取 0.456 0.280 ~39%
文件写入 0.321 0.215 ~33%
文本分词 2.143 1.331 ~38%
词频计算 1.897 0.942 ~50%
余弦相似度计算 3.568 1.476 ~59%
整体性能 45.32 15.637 ~66%

四、计算模块部分单元测试展示

1、单元测试代码

/*** 测试基本功能*/
private static void testBasicFunctionality() {System.out.println("\n--- 基本功能测试 ---");String original = "今天是星期天,天气晴,今天晚上我要去看电影。";String plagiarized = "今天是周天,天气晴朗,我晚上要去看电影。";String different = "这是一段完全不同的文本内容,与原文没有任何关系。";// 测试相同文本double sameSimilarity = PaperChecker.calculateSimilarity(original, original);System.out.printf("相同文本相似度: %.2f%%\n", sameSimilarity);// 测试相似文本double similarSimilarity = PaperChecker.calculateSimilarity(original, plagiarized);System.out.printf("相似文本相似度: %.2f%%\n", similarSimilarity);// 测试不同文本double differentSimilarity = PaperChecker.calculateSimilarity(original, different);System.out.printf("不同文本相似度: %.2f%%\n", differentSimilarity);
}/*** 测试多种算法*/
private static void testDifferentAlgorithms() {System.out.println("\n--- 多种算法测试 ---");String original = "今天是星期天,天气晴,今天晚上我要去看电影。";String plagiarized = "今天是周天,天气晴朗,我晚上要去看电影。";double cosineSimilarity = PaperChecker.calculateSimilarityWithCosine(original, plagiarized);double simpleMatchSimilarity = PaperChecker.calculateSimilarityWithSimpleMatch(original, plagiarized);double jaccardSimilarity = PaperChecker.calculateSimilarityWithJaccard(original, plagiarized);double simHashSimilarity = OptimizedPaperChecker.calculateSimilarityWithSimHash(original, plagiarized);System.out.printf("余弦相似度: %.2f%%\n", cosineSimilarity);System.out.printf("简单匹配相似度: %.2f%%\n", simpleMatchSimilarity);System.out.printf("Jaccard相似度: %.2f%%\n", jaccardSimilarity);System.out.printf("SimHash相似度: %.2f%%\n", simHashSimilarity);
}/*** 大规模数据测试*/
private static void testLargeScaleData() {System.out.println("\n--- 大规模数据测试 ---");// 创建大规模测试数据StringBuilder originalBuilder = new StringBuilder();StringBuilder plagiarizedBuilder = new StringBuilder();for (int i = 0; i < 10000; i++) {originalBuilder.append("这是一段用于大规模测试的文本内容,包含各种不同的词汇和句子结构。");if (i % 7 != 0) { // 约70%的内容保持一致plagiarizedBuilder.append("这是一段用于大规模测试的文本内容,包含各种不同的词汇和句子结构。");} else {plagiarizedBuilder.append("这是替换后的不同内容,用于测试算法在大规模数据下的表现和准确性。");}}String original = originalBuilder.toString();String plagiarized = plagiarizedBuilder.toString();// 测试优化算法和SimHash算法long startTime = System.currentTimeMillis();double optimizedResult = OptimizedPaperChecker.optimizedCalculateSimilarity(original, plagiarized);long optimizedTime = System.currentTimeMillis() - startTime;startTime = System.currentTimeMillis();double simHashResult = OptimizedPaperChecker.calculateSimilarityWithSimHash(original, plagiarized);long simHashTime = System.currentTimeMillis() - startTime;System.out.println("===== 大规模数据测试结果 ====");System.out.printf("优化余弦相似度算法: %d ms, 结果: %.2f%%\n", optimizedTime, optimizedResult);System.out.printf("SimHash算法: %d ms, 结果: %.2f%%\n", simHashTime, simHashResult);System.out.printf("预期相似度约为70%%,因为约30%%的内容被替换\n");
}

2、测试数据构造思路

2.1 基本功能测试

  • 构造相同文本:验证算法是否能正确识别完全相同的文本
  • 构造相似文本:验证算法对近义词、语序变化的敏感度
  • 构造不同文本:验证算法对完全不同内容的区分能力

2.2 多种算法测试

  • 使用相同的测试数据对比四种不同算法的结果差异
  • 分析各算法的优缺点和适用场景

2.3 大规模数据测试

  • 生成包含10000段文本的大规模测试数据
  • 控制相似度比例(约70%内容相同),验证算法在大数据量下的性能和准确性

五、计算模块部分异常处理说明

1、异常设计目标

本系统设计了以下几种异常处理机制,确保系统在各种情况下能够稳定运行:

参数验证异常:确保程序接收到正确的参数格式和数量
文件操作异常:处理文件不存在、权限不足等问题
内存溢出防护:避免处理超大文件时出现内存问题
算法计算异常:确保在边界情况下(如空文本)算法能够正常工作

2、异常处理示例

参数验证异常

public static void main(String[] args) {if (args.length != 3) {System.out.println("Usage: java -jar main.jar [原文文件] [抄袭版论文的文件] [答案文件]");System.exit(1);}// 后续代码...
}

场景说明:当用户未提供正确数量的命令行参数时,系统会显示正确的使用方法并退出,避免后续代码因参数错误而崩溃。

文件操作异常

try {// 开始测量整个程序执行时间PerformanceAnalyzer.start("整个程序执行");String originalText = readFile(originalFilePath);String plagiarizedText = readFile(plagiarizedFilePath);double similarity = calculateSimilarity(originalText, plagiarizedText);writeFile(outputFilePath, similarity);// 结束测量并打印性能统计PerformanceAnalyzer.end("整个程序执行");PerformanceAnalyzer.printStatistics();
} catch (Exception e) {e.printStackTrace();
}

场景说明:当文件不存在、路径错误或权限不足时,系统会捕获异常并打印详细的错误信息,方便用户排查问题。

边界情况处理

// 计算余弦相似度
static double calculateCosineSimilarity(Map<String, Integer> tf1, Map<String, Integer> tf2) {// 计算点积double dotProduct = 0;for (String word : tf1.keySet()) {if (tf2.containsKey(word)) {dotProduct += tf1.get(word) * tf2.get(word);}}// 计算向量长度double magnitude1 = 0;for (int count : tf1.values()) {magnitude1 += count * count;}magnitude1 = Math.sqrt(magnitude1);double magnitude2 = 0;for (int count : tf2.values()) {magnitude2 += count * count;}magnitude2 = Math.sqrt(magnitude2);// 计算余弦相似度if (magnitude1 == 0 || magnitude2 == 0) {return 0;  // 处理空向量情况}return dotProduct / (magnitude1 * magnitude2);
}

场景说明:当输入为空文本或两个文本没有共同词汇时,会出现向量模长为0的情况,此时返回相似度为0,避免除零异常。


六、总结

本论文查重系统通过采用多种相似度计算算法,实现了高效准确的文本相似度检测功能。通过性能分析和优化,我们成功将系统整体性能提升了约66%,特别是在处理大规模文本时表现更为突出。

系统的主要亮点包括:

  • 支持多种相似度计算算法(余弦相似度、简单词频匹配、Jaccard相似度、SimHash)
  • 提供了全面的性能分析工具,方便开发者进行性能优化
  • 针对中文文本特点进行了专门的分词优化
  • 具备良好的异常处理机制,确保系统稳定运行
  • 提供了丰富的测试方法,便于功能验证和性能评估

通过本项目,我不仅学习了各种文本相似度计算算法的原理和实现方法,还深入了解了性能分析和优化的技巧,提高了系统设计和代码实现的能力。

http://www.hskmm.com/?act=detail&tid=12206

相关文章:

  • WO Mic - 免费麦克风
  • AudioRelay —— 让电脑使用手机的麦克风和扬声器
  • 【小白学算法】矩阵快速幂超详细解析+例题[HDU - 2802]
  • lyms 的神秘歌单
  • 大学园区二手书交易强大的平台(代码+数据库+LW)
  • webRTC入门
  • Element UI框架中自定义input组件的placeholder样式
  • 【C++】类与结构体的区别
  • Linux云端服务器上部署Spring Boot应用
  • HTML表单验证:确认input元素输入为具有特定整数和小数位数的数值
  • 课前问题思考3
  • 在CentOS上配置SVN至Web目录的自动同步
  • AIGC在游戏开发中的革命性影响:从生产效率到体验创新 - 详解
  • 使用Docker配置并连接HBase的Java API
  • 在Linux环境下安装和卸载DMETL5数据迁移工具
  • 赛前训练3 欧拉路
  • SQL小贴式: 用NOT EXISTS 而不是 NOT IN !!!
  • 手撕大模型|FlashAttention 原理及代码解析
  • react工程化
  • CF700E Cool Slogans 做题记录
  • 完整教程:在 Ubuntu 上安装和配置 PostgreSQL 实录
  • 一个MCU与FPGA混合电路上电启动的问题及其解决办法探索[原创www.cnblogs.com/helesheng]
  • JMX与RMI
  • 通过主机监控发现路径遍历漏洞的实战技巧
  • Code New Roman 字体的正确下载方式
  • 多态是对于处理不同的变量,但是使用相同或者类似的方式。多态核心分为两种形式:编译时多态(静态多态)和运行时多态(动态多态)C++中多态通常使用虚函数或者指针(引用)实现。
  • 从 C++ 到 Python
  • Nipper 3.9.0 for Windows Linux - 网络设备漏洞评估
  • c++单例实践
  • NOIP 模拟赛九