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

个人编程作业

项目 内容
这个作业属于哪个课程 软件工程
这个作业要求在哪里 作业要求
这个作业的目标 训练个人项目软件开发能力,学会使用性能测试工具和实现单元测试优化程序

代码仓库:https://github.com/FZ688/3123004177-TextCheck
releases:https://github.com/FZ688/3123004177-TextCheck/releases/tag/V1.0.0

一、PSP表格

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

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

1. 代码组织结构

本论文查重程序主要包含5个核心类,它们的关系和职责如下:

  • Main:程序入口,处理命令行参数,协调各模块工作
  • SimilarityCalculator:核心计算类,实现相似度计算逻辑
  • TextProcessor:文本预处理工具类,负责文本清洗和分词
  • FileHandler:文件处理工具类,负责文件的读写操作
  • StringUtils:字符串工具类,实现编辑距离计算

类之间的关系如图所示:

image-20250923201821173

2. 核心算法设计

本程序采用两种相似度算法加权融合的方式计算文本重复率:

  1. 余弦相似度:基于词频向量计算

    • 将文本分词后构建词频向量
    • 计算两个向量的余弦夹角作为相似度度量
  2. 编辑距离相似度:基于Levenshtein距离

    • 计算两个文本之间的最小编辑操作数(插入、删除、替换)
    • 将编辑距离转换为相似度(1 - 编辑距离/最长文本长度)
  3. 加权融合:将两种相似度按照设定权重(默认0.7和0.3)进行加权计算

3. 关键函数流程图

主计算流程如下:

余弦相似度计算流程:

image-20250923201922940

4. 算法独到之处

  1. 结合两种相似度算法的优势,既考虑词频分布特征,又考虑字符级别的编辑差异
  2. 针对长文本进行停用词过滤,提高计算效率和准确性
  3. 预处理阶段对特殊符号和标点进行统一处理,减少干扰因素
  4. 支持中英文混合文本的处理,适应性更强

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

1. 性能改进过程

在完成初始版本后,使用JProfiler进行性能分析,发现以下性能瓶颈:

  1. 分词操作在处理长文本时耗时较长
  2. 余弦相似度计算中向量构建过程存在冗余操作
  3. 预处理阶段字符串替换操作效率不高

针对以上问题,采取了以下改进措施:

  1. 优化分词流程,减少不必要的对象创建
  2. 改用更高效的词频统计数据结构(HashMap -> ArrayMap)
  3. 合并预处理阶段的正则替换操作,减少字符串对象创建
  4. 对长文本采用分批处理策略,降低内存占用

性能优化花费时间约90分钟。

2. 性能分析图

优化后,程序的主要性能消耗集中在:

  • TextProcessor.segmentText():分词操作,约占总耗时的45%
  • SimilarityCalculator.calculateCosineSimilarity():余弦相似度计算,约占总耗时的30%

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

1. 部分单元测试代码

// 测试1: 学术文本余弦相似度(部分重复)
@Test
public void testCosineSimilarityAcademicPartial() {
    List<String> words1 = Arrays.asList("人工智能", "是", "研究", "如何", "使计算机", "模拟", "人类", "智能", "活动", "的", "科学");
    List<String> words2 = Arrays.asList("人工智能", "研究", "计算机", "如何", "实现", "类似", "人类", "的", "智能", "行为");
    double similarity = calculator.calculateCosineSimilarity(words1, words2);
    assertEquals(0.577, similarity, 0.001);
}

// 测试4: 轻度修改的论文段落(同义词替换)
@Test
public void testEditDistanceMildModification() {
    String text1 = "计算机视觉是人工智能的一个重要分支,它使计算机能够从图像或视频中获取高级理解。";
    String text2 = "机器视觉作为人工智能的关键领域,让计算机可以从图像和视频中获得高层级认知。";
    double similarity = calculator.calculateEditDistanceSimilarity(text1, text2);
    assertEquals(0.714, similarity, 0.001);
}

// 测试10: 包含特殊符号的文本
@Test
public void testTextWithSpecialSymbols() {
    String text1 = "算法复杂度分析中,O(n log n) 通常优于 O(n²),尤其是当 n 很大时。";
    String text2 = "在算法复杂度分析里 O n log n 一般比 O n² 更好 特别是当 n 很大的时候";
    double similarity = calculator.calculateSimilarity(text1, text2, 0.5, 0.5);
    assertEquals(0.833, similarity, 0.001);
}

2. 测试思路说明

测试用例设计主要考虑以下场景:

  • 完全相同的文本
  • 部分重复的学术文本
  • 不同领域的文本
  • 轻度修改(同义词替换)的文本
  • 结构调整的文本
  • 大幅修改但保留核心意思的文本
  • 包含特殊符号的文本
  • 极短文本
  • 中英文混合文本
  • 空文本或异常输入

通过覆盖这些场景,确保程序在各种情况下都能正确计算相似度。

3. 测试覆盖率

PixPin_2025-09-23_20-13-15

目前对主要的类(SimilarityCalculator)单元测试覆盖率达到100%,覆盖了所有核心计算逻辑和异常处理路径。

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

本程序设计了多种异常处理机制,确保程序的健壮性:

  1. 空文本异常

    • 设计目标:当输入文本为空时,提示用户无法进行查重
    • 测试用例:
    @Test(expected = IllegalArgumentException.class)
    public void testEmptyText() {
        calculator.calculateSimilarity("", "有效文本", 0.5, 0.5);
    }
    
    • 错误场景:用户输入空文件或仅包含空白字符的文件
  2. 文件不存在异常

    • 设计目标:当指定路径的文件不存在时,给出明确提示
    • 测试用例:
    @Test(expected = FileNotFoundException.class)
    public void testFileNotFound() throws IOException {
        FileHandler.readFile("nonexistent.txt");
    }
    
    • 错误场景:用户输入错误的文件路径或文件名
  3. 空指针异常

    • 设计目标:防止输入null值导致程序崩溃
    • 测试用例:
    @Test(expected = IllegalArgumentException.class)
    public void testNullInput() {
        calculator.calculateSimilarity(null, "文本", 0.5, 0.5);
    }
    
    • 错误场景:外部调用时传入null参数
  4. 参数非法异常

    • 设计目标:确保权重参数在有效范围内
    • 测试用例:
    @Test(expected = IllegalArgumentException.class)
    public void testInvalidWeight() {
        calculator.calculateSimilarity("文本1", "文本2", 1.5, -0.3);
    }
    
    • 错误场景:权重参数超出[0,1]范围

附录:程序使用说明

  1. 编译程序生成JAR包:main.jar
  2. 命令行运行:java -jar main.jar [原文文件路径] [抄袭版论文路径] [结果输出路径]
  3. 示例:java -jar main.jar C:\examples\orig.txt C:\examples\orig_add.txt C:\ans\ans.txt
  4. 输出结果为浮点型,精确到小数点后两位

程序支持处理中英文混合文本,能够有效识别各种形式的文本修改,计算结果准确可靠。

posted @ 2025-09-23 20:26  fz6668  阅读(11)  评论(0)    收藏  举报