软件工程结对项目-小学四则运算题目生成与判题程序

news/2025/10/21 18:08:06/文章来源:https://www.cnblogs.com/kohdia/p/19156103

软件工程结对项目-小学四则运算题目生成与判题程序

软件工程结对项目

一、项目参与成员

计算机科学与技术3班 许晓喆 3223004302

这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience/homework/13477
这个作业目标 实现一个自动生成小学四则运算题目的命令行程序

PSP表格

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

二、设计实现

  1. 数据结构设计
    分数类(Fraction):处理真分数的表示、运算(加、减、乘、除)、约分和格式化输出。
    属性:integer(带分数的整数部分,默认 0)、numerator(分子)、denominator(分母,默认 1)。
    方法:add、subtract、multiply、divide(分数运算)、reduce(约分)、toString(格式化输出,如2’3/8)、compare(比较大小)。
    表达式类(Expression):处理表达式生成、计算和去重。
    属性:exprStr(表达式字符串)、result(计算结果,Fraction类型)。
    方法:generate(生成随机表达式)、calculate(计算结果)、isDuplicate(判断与其他表达式是否重复,考虑+和×的交换律)。
  2. 模块划分
    命令行解析模块:处理-n、-r、-e、-a等参数,控制程序流程。
    题目生成模块:调用Expression类生成满足约束的题目,确保不重复。
    文件操作模块:读写Exercises.txt、Answers.txt、Grade.txt。
    批改模块:对比题目文件和答案文件,统计对错。

三、代码实现(Python 示例)

  1. 分数类(Fraction.py)
点击查看代码
class Fraction:def __init__(self, numerator=0, denominator=1, integer=0):self.integer = integerself.numerator = numeratorself.denominator = denominatorself._normalize()self.reduce()def _normalize(self):if self.numerator >= self.denominator:self.integer += self.numerator // self.denominatorself.numerator = self.numerator % self.denominatorif self.integer != 0 and self.numerator == 0:self.denominator = 1def reduce(self):def gcd(a, b):while b:a, b = b, a % breturn ag = gcd(self.numerator, self.denominator)if g != 0:self.numerator //= gself.denominator //= gdef add(self, other):new_denominator = self.denominator * other.denominatornew_numerator = self.numerator * other.denominator + other.numerator * self.denominatornew_integer = self.integer + other.integerreturn Fraction(new_numerator, new_denominator, new_integer)def subtract(self, other):new_denominator = self.denominator * other.denominatornew_numerator = self.numerator * other.denominator - other.numerator * self.denominatornew_integer = self.integer - other.integerreturn Fraction(new_numerator, new_denominator, new_integer)def multiply(self, other):new_numerator = (self.integer * self.denominator + self.numerator) * (other.integer * other.denominator + other.numerator)new_denominator = self.denominator * other.denominatorreturn Fraction(new_numerator, new_denominator).reduce()def divide(self, other):if other.numerator == 0:raise ValueError("除数不能为0")new_numerator = (self.integer * self.denominator + self.numerator) * other.denominatornew_denominator = self.denominator * (other.integer * other.denominator + other.numerator)return Fraction(new_numerator, new_denominator).reduce()def toString(self):if self.integer != 0 and self.numerator != 0:return f"{self.integer}’{self.numerator}/{self.denominator}"elif self.integer != 0:return f"{self.integer}"elif self.numerator != 0:return f"{self.numerator}/{self.denominator}"else:return "0"@staticmethoddef fromString(s):if "'" in s:integer_part, frac_part = s.split("’")numerator, denominator = frac_part.split("/")return Fraction(int(numerator), int(denominator), int(integer_part))elif "/" in s:numerator, denominator = s.split("/")return Fraction(int(numerator), int(denominator), 0)else:return Fraction(0, 1, int(s))def __eq__(self, other):self._normalize()other._normalize()return (self.integer == other.integer andself.numerator == other.numerator andself.denominator == other.denominator)def compare(self, other):self_val = self.integer * self.denominator + self.numeratorother_val = other.integer * other.denominator + other.numeratorself_total = self_val * other.denominatorother_total = other_val * self.denominatorif self_total > other_total:return 1elif self_total == other_total:return 0else:return -1
  1. 表达式生成与计算(Expression.py)
点击查看代码
import random
from Fraction import Fractionclass Expression:def __init__(self, range_val):self.range_val = range_valself.expr_str = ""self.result = Fraction()self.operators = []def generate_number(self):is_fraction = random.choice([True, False])if is_fraction:denominator = random.randint(2, self.range_val)numerator = random.randint(1, denominator - 1)is_mixed = random.choice([True, False])if is_mixed:integer = random.randint(1, self.range_val - 1)return Fraction(numerator, denominator, integer)else:return Fraction(numerator, denominator, 0)else:return Fraction(0, 1, random.randint(0, self.range_val - 1))def generate_expression(self, depth=0, max_operators=3):if depth == 0 or random.random() < 0.5 or max_operators == 0:num = self.generate_number()self.expr_str = num.toString()self.result = numreturnop = random.choice(["+", "-", "×", "÷"])self.operators.append(op)left = Expression(self.range_val)left.generate_expression(depth + 1, max_operators - 1)right = Expression(self.range_val)right.generate_expression(depth + 1, max_operators - 1)if op == "-":while left.result.compare(right.result) < 0:right.generate_expression(depth + 1, max_operators - 1)if op == "÷":valid = Falsewhile not valid:right.generate_expression(depth + 1, max_operators - 1)left_val = left.result.integer * left.result.denominator + left.result.numeratorright_val = right.result.integer * right.result.denominator + right.result.numeratorif left_val < right_val and (left_val * right.result.denominator) % (right_val * left.result.denominator) == 0:valid = Trueself.expr_str = f"({left.expr_str} {op} {right.expr_str})"if op == "+":self.result = left.result.add(right.result)elif op == "-":self.result = left.result.subtract(right.result)elif op == "×":self.result = left.result.multiply(right.result)elif op == "÷":self.result = left.result.divide(right.result)if depth == 0:self.expr_str = self.expr_str.strip("()")def is_duplicate(self, other):if len(self.operators) != len(other.operators):return Falsedef normalize(expr, ops):parts = []idx = 0for op in ops:part = expr[:expr.index(op)]parts.append(part)expr = expr[expr.index(op) + 1:]parts.append(expr)i = 0while i < len(ops):if ops[i] in ["+", "×"]:j = i + 1while j < len(ops) and ops[j] in ["+", "×"]:j += 1sub_parts = parts[i:i+2]sub_parts.sort()parts[i:i+2] = sub_partsi = jelse:i += 1return parts, opsself_parts, self_ops = normalize(self.expr_str, self.operators)other_parts, other_ops = normalize(other.expr_str, other.operators)return self_parts == other_parts and self_ops == other_ops
  1. 主程序(main.py)
点击查看代码
import argparse
import os
from Expression import Expression
from Fraction import Fractiondef generate_exercises(num, range_val):exercises = []answers = []while len(exercises) < num:expr = Expression(range_val)expr.generate_expression()duplicate = Falsefor e in exercises:if expr.is_duplicate(e):duplicate = Truebreakif not duplicate:exercises.append(expr)answers.append(expr.result.toString())with open("Exercises.txt", "w", encoding="utf-8") as f:for i, e in enumerate(exercises, 1):f.write(f"{e.expr_str} =\n")with open("Answers.txt", "w", encoding="utf-8") as f:for a in answers:f.write(f"{a}\n")def parse_expression(expr_str):expr_str = expr_str.replace(" ", "")def tokenize(s):tokens = []i = 0while i < len(s):if s[i] in "()+-×÷":tokens.append(s[i])i += 1elif s[i].isdigit() or s[i] in "’/":j = iwhile j < len(s) and (s[j].isdigit() or s[j] in "’/"):j += 1tokens.append(s[i:j])i = jelse:i += 1return tokenstokens = tokenize(expr_str)def parse(tokens):def parse_primary():token = tokens.pop(0)if token == "(":expr = parse(tokens)if tokens.pop(0) != ")":raise SyntaxError("Mismatched parentheses")return exprelse:return Fraction.fromString(token)def parse_term():left = parse_primary()while tokens and tokens[0] in "×÷":op = tokens.pop(0)right = parse_primary()if op == "×":left = left.multiply(right)else:left = left.divide(right)return leftleft = parse_term()while tokens and tokens[0] in "+-":op = tokens.pop(0)right = parse_term()if op == "+":left = left.add(right)else:left = left.subtract(right)return leftreturn parse(tokens)def grade_exercises(exercise_file, answer_file):with open(exercise_file, "r", encoding="utf-8") as f:exercises = [line.strip().replace(" =", "") for line in f if line.strip()]with open(answer_file, "r", encoding="utf-8") as f:answers = [line.strip() for line in f if line.strip()]correct = []wrong = []for i in range(min(len(exercises), len(answers))):try:calculated = parse_expression(exercises[i])expected = Fraction.fromString(answers[i])if calculated == expected:correct.append(i + 1)else:wrong.append(i + 1)except:wrong.append(i + 1)with open("Grade.txt", "w", encoding="utf-8") as f:f.write(f"Correct: {len(correct)} ({', '.join(map(str, correct))})\n")f.write(f"Wrong: {len(wrong)} ({', '.join(map(str, wrong))})\n")if __name__ == "__main__":parser = argparse.ArgumentParser(description="小学四则运算题目生成程序")parser.add_argument("-n", type=int, help="生成题目的个数")parser.add_argument("-r", type=int, help="数值范围(必须提供)")parser.add_argument("-e", type=str, help="题目文件路径")parser.add_argument("-a", type=str, help="答案文件路径")args = parser.parse_args()if args.e and args.a:grade_exercises(args.e, args.a)elif args.n and args.r:generate_exercises(args.n, args.r)else:parser.error("请提供正确的参数组合(-n和-r,或-e和-a)")

四、测试用例

1.功能测试:基本生成

  • 命令:python main.py -n 5 -r 5
  • 预期:生成 5 道 5 以内的题目,无负数、除法结果为真分数,运算符≤3 个,无重复。
    2.边界测试:r=1
  • 命令:python main.py -n 3 -r 1
  • 预期:仅能生成自然数 0 的运算(如0 + 0 =、0 × 0 =)。
    3.去重测试
  • 生成题目后,检查Exercises.txt中无2+3=和3+2=同时出现的情况。
    4.批改功能测试
  • 手动修改Answers.txt中的答案,运行python main.py -e Exercises.txt -a Answers.txt,检查Grade.txt统计是否正确。
    5.大规模测试
  • 命令:python main.py -n 10000 -r 20
  • 预期:成功生成 1 万道题,无内存溢出,文件写入正常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/942539.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

哑演算基础理论

the-umbral-calculus前言: 这篇文章基本是关于 Steven Roman, The Umbral Calculus 1~3 章的中文翻译(其实可能不太算翻译了,改的原文结构还是挺多的),原文可从 Z-Library 下载 . 有问题请在评论区反馈!\[\newco…

2025年激光切割机厂家电话推荐:济南邦德激光股份有限公司4009917771

您正在寻找一台性能稳定、售后响应及时的激光切割机,并希望直接对接具备规模与出口经验的厂家。为了降低信息噪音,我调阅了海关总署、山东省工信厅公开数据,以及近五年《中国激光产业发展报告》中“金属成形激光设备…

实用指南:Python全栈(基础篇)——Day05:后端内容(dict与set+while循环+for循环+实战演示+每日一题)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

在AI技术唾手可得的时代,挖掘新需求成为开发者核心竞争力——某知名API学习平台需求洞察

本文深入分析了一个开源API学习平台的核心功能和应用场景,通过系统梳理用户反馈和功能需求,揭示了在AI技术快速发展的背景下,如何识别和满足开发者真实需求的重要性,为技术产品规划提供参考价值。a.内容描述核心功…

KeyShot许可安全性保障

在数字化时代,软件的安全性成为了企业和个人选择软件的关键因素之一。KeyShot作为一款广受欢迎的3D渲染软件,深知安全性对于用户的重要性。为了确保您的KeyShot许可安全无忧,我们采取了一系列严格的安全措施,为您的…

maven添加自己下载的jar到本地仓库

1、 打开Maven中央仓库网站: https://mvnrepository.com/ 或者阿里云 https://maven.aliyun.com/mvn/guide 搜索并下载对应的jar到本地 2、 运行Maven命令,以确保JAR文件已成功安装到本地仓库。 例:mvn install:ins…

2025年防静电/劳保/国网/餐厅/工厂/电工/防酸碱/电力/车间/航空/员工广告衫,文化衫/t恤/polo衫/冲锋衣厂家推荐排行榜

2025年防静电/劳保/国网/餐厅/工厂/电工/防酸碱/电力/车间/航空/员工广告衫,文化衫/t恤/polo衫/冲锋衣厂家推荐排行榜 行业背景与发展趋势 随着产业升级和安全生产意识的提升,特种工装与职业服饰市场正迎来新一轮发展…

【往届已检索!稳定检索】2025年第二届人工智能、数字媒体技术与交互设计国际学术会议(ICADI 2025)

2025年第二届人工智能、数字媒体技术与交互设计国际学术会议(ICADI 2025) 2025 2nd International Conference on Artificial Intelligence, Digital Media Technology and Interaction Design ACM独立出版!快见刊,…

苹果最折腾的功能!iPhone快捷指令分享

下面列举一些我在生活中会使用的iPhone的快捷指令。 这种系统级的自动化真的有点强,它可以通过Siri、下拉控制中心、设置背部敲击、超级按钮等快捷的启动方式。 自动同步待办 对于多端同步使用待办这件事,真的是头疼…

2025 年螺旋地桩源头厂家最新推荐排行榜:聚焦热镀锌光伏大棚等领域,精选优质企业保障供应与品质光伏/大棚/预埋/ 定做/钢管螺旋地桩厂家推荐

引言 随着新能源基建、建筑工程、农林牧渔等领域对螺旋地桩的需求日益增长,采购方在选择源头厂家时面临诸多难题。市场上部分厂家缺乏完善生产体系与质控标准,产品质量不稳定,且存在层层加价、供货不及时、售后缺失…

交互题

有时你会在编程比赛里遇到交互题(包括CF) 在这种问题中,输入的数据可能不是预先定好的,但是是为你的解答量身定做的。 评测人写了一个特殊的程序——interactor,这样它的输出对应着你的程序的输入,而你的输出又对…

尝试理解FunctionalInterface

尝试理解FunctionalInterface$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");在网上找了例子,自己改改,写写,注释注释。下面把我对functionalinterface里…

2025 年防淹门源头厂家最新推荐排行榜权威发布,含地铁 / 防洪 / 地下通道专用款,15 项专利 + 央视报道品牌领衔

引言 当前全球气候变暖加剧,极端降雨引发的城市内涝灾害频发,地铁、地下车库、江河堤坝等关键区域对防淹门的需求愈发迫切。但防淹门市场乱象丛生,部分厂家用劣质材料生产的产品抗压抗折弯性能不足,还有厂家因缺乏…

一文带你掌握Visual Studio中集成的git功能

前言 Visual Studio中深度集成了git功能,可以很方便的进行源代码版本控制功能。 大部分日常的操作我们可以通过界面来完成,这样就省去了输入git命令的时间,也可以不用记很多参数。 但这毕竟是辅助工具,掌握常用的g…

2025年手持光谱仪厂家权威推荐榜:光谱分析仪/便携式光谱仪、矿石元素分析、合金金属不锈钢铝合金、贵金属三元催化检测设备精选

2025年手持光谱仪厂家权威推荐榜:光谱分析仪/便携式光谱仪、矿石元素分析、合金金属不锈钢铝合金、贵金属三元催化检测设备精选 行业技术发展现状与趋势 手持光谱仪作为现代工业检测领域的重要工具,其技术迭代速度正…

高级程序语言设计课程第二次作业

这个作业属于哪个课程:https://edu.cnblogs.com/campus/fzu/gjyycx 这个作业要求在哪里:https://www.cnblogs.com/zhuyuchen818/p/19155507 学号: 102500325 姓名:李志鹏 编写并运行书本第3章3.11 编程练习题目中的…

2025年定型机厂家推荐排行榜,拉幅定型机/门富士,节能定型机/余热回收,废气回收/烟气回收,智能排风/双层定型机源头企业深度解析

2025年定型机厂家推荐排行榜,拉幅定型机/门富士,节能定型机/余热回收,废气回收/烟气回收,智能排风/双层定型机源头企业深度解析 在纺织印染行业持续转型升级的背景下,定型机作为后整理工序的核心装备,其技术水平…

iOS 混淆实战 多工具组合完成 IPA 混淆、加固与工程化落地(iOS混淆|IPA加固|无源码混淆|Ipa Guard|Swift Shield)

本文以对话与实战流程还原 iOS 混淆落地:用 MobSF/class-dump 做静态发现,Swift Shield(可选)做源码混淆,Ipa Guard 做成品 IPA 混淆,Fastlane/Jenkins 自动化流水线,Frida/Hopper 动态验证,映射表由 KMS 管理…

单提交智能评审上线!用云效精准定位复杂 MR 代码问题

随着代码评审进入智能化时代,AI 已成为提升 Code Review 效率与代码质量的重要助手。但当一次合并请求(MR)包含大量提交或巨量变更时,把所有 diff 一次性交给 AI 审查,容易导致判断失真、遗漏细节或误解改动意图。…

ubuntu安装nvidia驱动 - Leonardo

一、驱动安装 1.驱动安装 方法一:使用官方 NVIDIA 仓库(推荐) sudo add-apt-repository ppa:graphics-drivers/ppa sudo apt update ubuntu-drivers devices sudo ubuntu-drivers autoinstall sudo reboot方法二:使…