MIPS中div.d指令精度异常:输出无法正确保留两位小数
解决MIPS汇编div.d指令后的浮点数精度输出问题
问题原因
这是二进制浮点数的精度局限性导致的:十进制的20.3无法被双精度浮点数精确存储,存入寄存器时本身就带有微小的误差。当你用div.d除以10.0后,这个误差被保留下来,即便格式化字符串指定了%.2f,底层数值的偏差还是会显示出多余的位数。而像10.5这类能被二进制精确表示的数,或者mul.d乘100.0时误差被放大到可精确表示的范围,就不会出现这个问题。
解决方案:输出前手动四舍五入到两位小数
在输出结果前,先对计算值进行四舍五入处理,把微小误差修正为精确到两位小数的数值。修改后的代码如下:
.data input1: .asciiz "Please enter what unit do you want to convert it into: \n" ask: .asciiz "Please enter the length\n" mmtocm: .double 10.0 hundred: .double 100.0 half: .double 0.5 result: .asciiz "The result is: %.2f\n" .text MAIN: # 打印输入提示 li $v0, 4 la $a0, ask syscall # 读取双精度长度值 li $v0, 7 syscall # 执行单位转换(mm转cm) l.d $f4, mmtocm div.d $f12, $f0, $f4 # 四舍五入到两位小数:乘100 → 加0.5 → 取整 → 除以100 l.d $f4, hundred mul.d $f12, $f12, $f4 # 将两位小数转为整数位 l.d $f4, half add.d $f12, $f12, $f4 # 加0.5,为四舍五入做准备 cvt.w.d $f12, $f12 # 转整数,自动截断小数部分(等价于四舍五入) cvt.d.w $f12, $f12 # 转回双精度浮点数 l.d $f4, hundred div.d $f12, $f12, $f4 # 还原为两位小数格式 # 打印结果 la $a0, result li $v0, 3 syscall Exit: li $v0, 10 syscall
处理逻辑说明
- 先把转换结果乘以100,把需要保留的两位小数部分提升为整数位;
- 加上0.5,让小数部分≥0.5的数值自动进位,实现四舍五入;
- 转换为整数类型截断小数,再转回双精度;
- 最后除以100,得到精确到两位小数的最终值。
经过这个处理后,输入20.3时会输出正确的2.03。
内容的提问来源于stack exchange,提问作者meliona aguendelo
相关产品推荐
相关产品推荐

