太空失重模拟Python代码问题:无法通过2个隐藏测试
太空失重模拟代码问题排查与修复
问题描述
这段模拟太空失重环境下人体肌肉与骨骼质量变化的Python代码可正常运行,但无法通过2个隐藏测试,怀疑问题出在精度或计算逻辑上。
现有代码
inputs = input() simulation_days = int(inputs.split(" ")[0]) initial_bone_mass = float(inputs.split(" ")[1]) initial_muscle_mass = float(inputs.split(" ")[2]) final_muscle_mass = initial_muscle_mass final_bone_mass = initial_bone_mass for day in range(simulation_days): final_muscle_mass *= (1 - 0.02) final_bone_mass *= (1 - 0.015) final_bone_mass += 0.02 * final_muscle_mass final_muscle_mass -= 0.02 * final_muscle_mass print(f"Final Muscle Mass: {final_muscle_mass:.2f} kg and Final Bone Mass: {final_bone_mass:.2f} kg")
任务规则
- 肌肉质量每日减少2%
- 骨骼质量每日减少1.5%
- 每日有2%的肌肉液体转移至骨骼
示例
- 输入:
4 40 60,输出:Final Muscle Mass: 51.05 kg and Final Bone Mass: 41.98 kg - 输入:
30 50 50,输出:Final Muscle Mass: 14.88 kg and Final Bone Mass: 45.23 kg
问题排查与修复
核心问题:浮点数精度累积误差
Python的float类型是双精度浮点数,在多次循环的乘法、加法运算中会产生微小精度损失。当隐藏测试用例对结果精度要求极高时,这种误差会导致最终格式化后的小数位与预期不符,从而无法通过测试。
同时原代码存在冗余运算:final_muscle_mass -= 0.02 * final_muscle_mass等价于final_muscle_mass *= 0.98,结合之前的final_muscle_mass *= 0.98,可合并为一次乘法操作减少运算步骤。
修复方案:使用高精度Decimal计算
改用decimal模块进行高精度运算,避免浮点数误差,同时优化计算逻辑:
from decimal import Decimal, getcontext # 设置足够的计算精度,避免累积误差 getcontext().prec = 12 # 读取输入并转换为Decimal类型 inputs = input().split() simulation_days = int(inputs[0]) initial_bone = Decimal(inputs[1]) initial_muscle = Decimal(inputs[2]) muscle = initial_muscle bone = initial_bone # 预定义常量,避免重复计算 MUSCLE_DAILY_RATE = Decimal('0.98') ** 2 # 每日总减少比例:先减2%,再转移2% BONE_REDUCE_RATE = Decimal('0.985') TRANSFER_RATE = Decimal('0.02') for _ in range(simulation_days): # 先计算肌肉当日减少2%后的临时值,用于计算转移量 muscle_after_first_reduce = muscle * Decimal('0.98') transfer_amount = muscle_after_first_reduce * TRANSFER_RATE # 更新骨骼质量:先减少1.5%,再加转移量 bone = bone * BONE_REDUCE_RATE + transfer_amount # 更新肌肉质量:两次减少2%的等效操作 muscle = muscle * MUSCLE_DAILY_RATE # 四舍五入到两位小数,确保输出符合要求 final_muscle = round(muscle, 2) final_bone = round(bone, 2) # 格式化输出 print(f"Final Muscle Mass: {final_muscle:.2f} kg and Final Bone Mass: {final_bone:.2f} kg")
修复说明
- 高精度计算:使用
Decimal类型替代float,设置足够精度避免循环运算中的精度损失。 - 逻辑优化:将肌肉的两次2%减少合并为一次乘法运算,同时明确转移量的计算基于第一次减少后的肌肉值,与原代码逻辑保持一致。
- 顺序对齐:保持骨骼先减少再增加转移量的顺序,与原代码逻辑对齐,确保符合任务规则的执行顺序。
内容的提问来源于stack exchange,提问作者אורי בן משה
相关产品推荐
相关产品推荐

