我已将问题浓缩为以下代码:
.data
newline: .asciiz "\n"
.text
.globl main
main:
li $t0, 4
li $t1, 16
mtc1 $t0, $f2 # Two integers get stored as floats
mtc1 $t1, $f30
div.d $f12, $f2, $f30
li $v0, 3
syscall # First division works, returns 0.25
la $a0, newline
li $v0, 4
syscall # prints new line
div.d $f12, $f12, $f30
li $v0, 3
syscall # Second division doesn't work as expected, returns Infinity
输出是:
0.25
Infinity
为什么?我希望0.25/16
为0.015625
而不是Infinity
。
$ f12的第一个值:0x3fd0000000000000 $ f12的第二个值:0x7ff0000000000000
我对MIPS比较新,所以它可能很简单。 谢谢你的回答!
答案 0 :(得分:3)
第一次划分的明显成功是由于如何表示小正整数和正次正常双精度的假象。两者都具有前导零,其中二进制位模式对应于最低有效位中的有效位的有效位。将整数视为双精度的效果是将每个值除以2的幂1074。
尽管f2和f30(被视为双精度浮点数)包含微小的值,约为2.0E-323和7.9E-323,但它们的比率与4/16相同。将一个中等数字(如0.25)除以一个小数字就会溢出到无穷大。
这是一个简短的Java程序,说明了这一点:
public class Test {
public static void main(String[] args) {
long t0 = 4;
long t1 = 16;
double f2 = Double.longBitsToDouble(t0);
double f30 = Double.longBitsToDouble(t1);
System.out.println("f2=" + f2);
System.out.println("f30=" + f30);
double f12 = f2 / f30;
System.out.println("f12=" + f12);
System.out.println("f12/f30=" + f12 / f30);
}
}
输出:
f2=2.0E-323
f30=7.9E-323
f12=0.25
f12/f30=Infinity