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

前三次作业总结

(1)前言

1.1 作业集概述
本阶段三次作业围绕“航空器配载与货运管理”这一真实业务场景展开,从基础的货运配载逐步演进到多货舱管理,最终实现完整的载重平衡计算系统。这是一个典型的渐进式课程设计,体现了软件工程中“增量开发”和“迭代优化”的核心理念。

1.2 知识点分布统计

作业阶段 核心知识点 技术难点 涉及类数量
第一次作业 单一职责原则、冒泡排序、集合框架 排序算法手写实现 4
第二次作业 组合/聚合关系、UML类图设计 货舱与位置的生命周期管理 6
第三次作业 力矩物理计算、配平公式、输入校验 浮点数精度处理、业务算法实现 10

 

 

 

 

1.3 题量与难度分析
题量分布:三次作业均为1道大题,但需求描述从500字逐步增加到1500字,类数量从4个扩展到10个

难度曲线:呈阶梯式上升

第一次作业:基础实现,重点在排序和类设计

第二次作业:引入多货舱概念,重点在组合/聚合关系

第三次作业:增加旅客和力矩计算,重点在业务算法和鲁棒性

 

(2)设计与分析

2.1 第一次作业——基础货运配载模块
2.1.1 类图设计

image

 

2.1.2 源码核心逻辑分析
排序算法的实现细节:

 

public void sortCargoByWeightDesc() {
int size = cargoList.size();
// 外层循环控制比较轮数,共需要 size-1 轮
for (int i = size - 1; i > 0; i--) {
bubblePass(i); // 每轮将最小的元素沉到底部
}
}

private void bubblePass(int end) {
// 内层循环进行相邻元素比较和交换
for (int j = 0; j < end; j++) {
if (cargoList.get(j).getWeight() < cargoList.get(j + 1).getWeight()) {
swap(j, j + 1); // 逆序则交换
}
}
}
这种实现方式将排序算法拆分为两个方法,体现了方法级别的单一职责。

超载判断的精度处理:

private boolean isOverload(double totalWeight) {
// 使用1e-6的容忍阈值避免浮点数精度误差
return totalWeight - maxWeight > 0.000001;
}

 

2.2 第二次作业——多货舱划分管理
2.2.1 类图设计(PlantUML)

image

 

2.2.2 组合与聚合的实现差异
组合关系(Composition)——货舱与位置:

 

public CargoCompartment(String id, double maxWeight, int rows, int cols) {
this.positions = new ArrayList<>();
// 位置对象在货舱构造器内部创建
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
positions.add(new Position(i, j));
}
}
// 位置的生命周期与货舱完全一致
}
聚合关系(Aggregation)——货舱与货物:

 

public boolean addCargo(Cargo cargo) {
if (canAddCargo(cargo.getWeight())) {
cargos.add(cargo); // 货物对象从外部传入
currentWeight += cargo.getWeight();
return true;
}
return false;
}
// 货物可以独立存在,货舱销毁时货物不会被销毁

 

2.3 第三次作业——载重平衡计算系统
2.3.1 完整类图设计(PlantUML)

image

 

2.3.2 力矩与重心计算公式实现
核心业务算法:

 

public void generateLoadSheet(Flight flight) {
// 第一步:旅客重量及力矩
double passengerWeight = flight.getPassengerTotalWeight();
double passengerMoment = passengerWeight * PASSENGER_ARM;

// 第二步:货舱重量及力矩(前舱和后舱力臂不同)
double cargoWeight = 0.0;
double cargoMoment = 0.0;
for (CargoCompartment comp : flight.getCompartments()) {
cargoWeight += comp.getCurrentWeight();
if (comp.getId().equals("1")) {
cargoMoment += comp.getCurrentWeight() * FRONT_ARM;
} else if (comp.getId().equals("2")) {
cargoMoment += comp.getCurrentWeight() * REAR_ARM;
}
}

// 第三步:全机总重量与总力矩
double totalWeight = EMPTY_WEIGHT + passengerWeight + cargoWeight;
double totalMoment = EMPTY_WEIGHT * EMPTY_ARM + passengerMoment + cargoMoment;

// 第四步:实际重心
double actualCG = totalMoment / totalWeight;

// 第五步:重心百分比(%MAC)
double cgPercent = (actualCG - MAC_LEADING_EDGE) / MAC_LENGTH * 100.0;

// 第六步:安全评估
boolean isSafe = cgPercent >= SAFE_MIN && cgPercent <= SAFE_MAX;
}
2.3.3 浮点数精度处理的演进
第一次作业到第三次作业,精度处理逐步完善:

 

// 第一次作业:简单的直接比较
if (currentWeight + weight > maxWeight) { ... }

// 第二次作业:引入阈值概念
if (currentWeight + weight > maxWeight + 0.000001) { ... }

// 第三次作业:统一精度处理方式,抽取为常量
private static final double EPSILON = 1e-6;
if (currentWeight + weight > maxWeight + EPSILON) { ... }

(3)采坑心得

3.1 浮点数精度问题的深入分析
问题复现:

// 输入:前舱最大载重5000,货物重量6000
double current = 0.0;
double weight = 6000.0;
if (current + weight <= 5000.0) { // 6000 <= 5000 ? false
// 正确判断为false
}

// 但实际测试中,由于浮点运算误差,可能出现:
// 6000.0 - 5000.0 = 999.999999999 而不是 1000.0
根本原因: IEEE 754浮点数标准中,十进制小数无法精确表示为二进制分数,导致计算误差。

解决方案演进:

 

// 方案1:使用阈值(最终采用)
private static final double EPSILON = 1e-6;
if (current + weight > maxWeight + EPSILON) {
// 超载
}

// 方案2:使用BigDecimal(精度最高但性能差)
BigDecimal currentBD = BigDecimal.valueOf(current);
BigDecimal weightBD = BigDecimal.valueOf(weight);
BigDecimal maxBD = BigDecimal.valueOf(maxWeight);
if (currentBD.add(weightBD).compareTo(maxBD) > 0) { ... }

// 方案3:转换为整数(但重量可能带小数,不适合)


3.2 排序算法稳定性问题
问题描述: 题目要求“同等重量的货物按输入的先后顺序排列”,这意味着需要使用稳定排序。

错误示例——选择排序(不稳定):

 

// 选择排序会破坏相等元素的原始顺序
for (int i = 0; i < n - 1; i++) {
int maxIdx = i;
for (int j = i + 1; j < n; j++) {
if (cargos.get(j).getWeight() > cargos.get(maxIdx).getWeight()) {
maxIdx = j; // 相等时不交换,但后续可能被移动
}
}
swap(cargos, i, maxIdx);
}
正确示例——冒泡排序(稳定):

 

// 冒泡排序只在严格大于时才交换,保持了相等元素的相对位置
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (cargos.get(j).getWeight() < cargos.get(j + 1).getWeight()) {
swap(cargos, j, j + 1); // 只有大于才交换
}
}
}


3.3 警告信息输出的时机与格式
错误示例:

 

// 在添加货物后检查超载
if (!compartment.addCargo(cargo)) {
// 此时货物未添加,当前载重未变
printCapacityWarning("1", compartment.getCurrentWeight(), maxWeight);
}
// 输出:!!! 警告:[1]剩余容量不足(0.0/5000.0kg)
// 期望:!!! 警告:[1]剩余容量不足(6000.0/5000.0kg)
正确实现:

 

// 添加前检查,并计算尝试后的重量
double attemptedWeight = compartment.getCurrentWeight() + cargoWeight;
if (attemptedWeight > compartment.getMaxWeight() + 0.000001) {
printCapacityWarning("1", attemptedWeight, compartment.getMaxWeight());
}
compartment.addCargo(cargo);

(4)改进建议

4.1 使用枚举管理常量

// 当前:常量散落在各类中
private static final double EMPTY_WEIGHT = 40000.0;
private static final double FRONT_ARM = 12.0;

// 改进:使用枚举统一管理
public enum AircraftConstants {
EMPTY(40000.0, 16.25),
FRONT_CARGO(0.0, 12.0),
REAR_CARGO(0.0, 22.0),
PASSENGER(0.0, 18.0);

private final double weight;
private final double arm;

AircraftConstants(double weight, double arm) {
this.weight = weight;
this.arm = arm;
}
// getters...
}


4.2 策略模式替代条件分支

// 当前:大量if-else判断货舱类型
if (comp.getId().equals("1")) {
arm = FRONT_ARM;
} else if (comp.getId().equals("2")) {
arm = REAR_ARM;
}

// 改进:在CargoCompartment构造时注入力臂
public CargoCompartment(String id, double maxWeight, int rows, int cols, double arm) {
this.id = id;
this.maxWeight = maxWeight;
this.arm = arm; // 不再需要外部判断
// ...
}

(5)总结

说真的,这三次作业做下来,感觉还是挺折腾的,但回头看看也确实学到了不少东西。第一次作业还算温柔,就是基本的货物装载和排序,主要让我搞明白了单一职责到底是咋回事——原来一个类真不能啥都往里塞,得拆开,不然代码写到后面自己都看不下去了。第二次作业突然加了多货舱,组合和聚合的关系我琢磨了好一阵子,刚开始老搞混,后来画了几遍类图才算整明白。第三次作业是真有点懵,力矩、重心百分比这些物理公式都搬出来了,不过硬着头皮把公式实现之后,发现其实也没那么可怕,就是一步步算下来就行。

感觉自己在代码拆分上还有待提高,虽然分了类,但有些方法还是写得有点长。要是以后有时间,想把那堆if-else改成用枚举或者策略模式,应该会更优雅一些。另外单元测试这块基本没碰,全靠手动输入测试,效率确实低。

总的来说,这三次作业虽然写得挺累,但确实让我对面向对象设计有了更深的理解,尤其是类之间关系的把握,比以前清楚多了。希望以后还能多来点这种循序渐进的设计题,比一次性扔个大作业要友好得多。

http://www.jsqmd.com/news/835544/

相关文章:

  • 泉州上门开锁哪家靠谱?泉州开锁换锁修锁商家实测对比|公安备案、同城极速上门推荐 - 速递信息
  • 在职法考通勤时间用哪个APP刷题?揽星法考APP,通勤刷题效率天花板 - 速递信息
  • 深耕成都同城短视频运营 百抖获客助力实体门店高效拓客 - 速递信息
  • 快手去水印怎么操作?快手视频去水印的在线解析工具和方法实测对比|2026年最新指南 - 科技热点发布
  • 2026年手机免费一键去水印App排行|哪款最好用?实测推荐指南 - 科技热点发布
  • 【深度解析】砌块工厂:生产流程、技术优势与行业实践 - 速递信息
  • 6、IntelliJ IDEA 之工程模块管理
  • 2026成都整装品质竞争加剧 彩兔装饰工艺量化与巡检深度获测评认可 - 速递信息
  • 从三个人天天加班到一个人轻松搞定:剪流GEO拯救了我的发际线 - 速递信息
  • 2026成都整装进入数据说话时代 彩兔装饰公开104项节点与862天记录 - 速递信息
  • 关于塑料桶出现应力开裂问题的分析 - 速递信息
  • 佛山大学 2024—2025 届就业优势深度报告暨未来5年就业发展预测:湾区智造高地 就业质量标杆 - 寻茫精选
  • 视频号视频怎么下载到相册?苹果手机和安卓手机保存方法 2026 实测 - 科技热点发布
  • 快手去水印怎么操作?快手视频如何在线去除水印?2026 在线工具实测推荐 - 科技热点发布
  • 20260517
  • 2026成都整装测评:从104个节点到七层验收,品控体系成核心竞争力 - 速递信息
  • 作业集1~3的总结性Blog
  • 抖音在线去水印怎么做?2026年抖音解析去水印平台推荐与操作详解 - 科技热点发布
  • 泉州丰泽开锁哪家靠谱|李氏开锁24小时上门,公安备案同城就近派单(2026最新) - 速递信息
  • 小红书怎样关闭下载水印?2026实测去水印方法全覆盖 - 科技热点发布
  • 2026年砌块工厂深度选型指南:如何为工程采购匹配最佳方案? - 速递信息
  • 2026届毕业论文降AI实测:DeepSeek手搓指令vs专用降AI工具,谁在收智商税? - 降AI实验室
  • 微服务间 Feign 调用传递 Token 丢失导致 401 未授权怎么解决?
  • 2026 iOS/安卓手机免费去水印App推荐|一键去除视频图片水印的软件测评 - 科技热点发布
  • 抖音视频怎样在线去水印?2026实测解析去水印操作方法与平台推荐 - 科技热点发布
  • 钢格板厂家常见问题解答(2026最新专家版) - 速递信息
  • 砌块工厂选购指南:如何选到靠谱的砌块生产供应商? - 速递信息
  • 佛山大学 2024—2025届就业优势深度全景报告:湾区智造高地、就业质量标杆 - 寻茫精选
  • 豆包视频怎么去水印?2026 去掉水印保存无水印视频的方法大全 - 科技热点发布
  • 提前3天交付!钢格板厂家电厂项目案例解析 - 速递信息