递归幂运算MIPS代码的浮点数精度问题排查
递归幂计算的精度问题:是架构问题还是代码错误?
我编写了一段用于递归计算数值幂的MIPS代码,整体逻辑看似正确,但测试时得到5^-2 = 0.04000000000000001的结果。想请教这个情况是计算机架构导致的,还是代码存在错误?
数据段中包含一个double类型数组和一个整数幂数组,代码如下:
.data double_array: .double 5.0 2.0 -3.0 -3.0 -4.2 5.0 -2.0 0.0 0.0 power_array: .word -2 -4 2 1 0 -2 -3 0 10 N_OF_CASES: .word 9 str_case: .asciiz "case_" str_colon: .asciiz ": " str_equal: .asciiz " = " str_power: .asciiz "^" str_newLine: .asciiz "\n" one: .double 1.0 zero: .double 0.0 main: lw $t1, N_OF_CASES la $t2, double_array la $t3, power_array li $t4, 0 loop: lw $a1, ($t3) lw $t0, ($t3) l.d $f14, ($t2) l.d $f16, ($t2) jal power li $v0, 3 mov.d $f12, $f16 syscall li $v0, 4 la $a0, str_power syscall li $v0, 1 move $a0, $t0 syscall li $v0, 4 la $a0, str_equal syscall li $v0, 3 mov.d $f12, $f0 syscall la $v0, 4 la $a0, str_newLine syscall addi $t2, $t2, 8 addi $t3, $t3, 4 addi $t4, $t4, 1 subi $t1, $t1, 1 bnez $t1, loop li $v0 10 syscall power: andi $sp 0xfffffff8 addi $sp $sp -16 s.d $f20 ($sp) sw $ra 8($sp) li $t7, 0 beq $a1, $t7, base_case bgez $a1, not_negative l.d $f2, one div.d $f14, $f2, $f14 li $t6, -1 mul $a1, $a1, $t6 j power not_negative: mov.d $f2, $f14 subi $a1, $a1, 1 jal power mul.d $f0, $f0, $f2 power_done: l.d $f20, ($sp) lw $ra, 8($sp) addi $sp, $sp, 16 jr $ra base_case: l.d, $f0, one j power_done
问题分析
这个精度误差不是代码错误,也不是MIPS架构的问题,而是IEEE 754浮点数二进制表示的固有特性:
- 0.04等价于1/25,而二进制小数只能精确表示分母是2的幂的分数(比如1/2=0.1₂,1/4=0.01₂)。25无法分解为2的整数次幂,因此0.04无法用二进制浮点数精确存储,只能用最接近的近似值代替,输出时就会显示出类似
0.04000000000000001的微小偏差。
代码逻辑验证
你的代码逻辑是正确的:
- 负幂处理:将底数取倒数,同时把幂转为正数,符合数学定义
- 递归逻辑:正幂时通过递归逐步累乘,基准情况(幂为0)返回1.0,完全符合幂运算规则
- 栈操作:正确保存和恢复了
$f20和$ra寄存器,没有栈溢出或寄存器冲突问题
总结:代码本身没有错误,结果的微小误差是所有遵循IEEE 754标准的浮点数系统都会出现的正常现象。
内容的提问来源于stack exchange,提问作者Alibi Tolebay
相关产品推荐
相关产品推荐

