MIPS 如何计算大于 1.111 x2^1023 的数字?

MIPS How can I calculate numbers greater than 1.111 x2^1023?

我正在使用 MIPS 和 MARS 4.5。 有什么方法可以计算扩展 1.111.. * 2^1023 范围的数字吗?

例如(阶乘函数):

.data
     dval:    .double   171.0  # its working up to 170!
     one:     .double   1.0  

.text
     l.d      $f2, dval
     l.d      $f4, one
     l.d      $f12, one
lo:  c.eq.d   $f2, $f4          # calc factorial of 171 = Infinity 
     bc1t     ex
     mul.d    $f12, $f12, $f2
     sub.d    $f2, $f2, $f4
     j        lo
ex:  li       $v0, 3
     syscall

如何计算和打印 171 的阶乘?

在 FP 中计算阶乘令人惊讶。 FP 数的精度受其尾数限制,实际上高于 ~20!,您需要超过 54 位来存储(整数)值,并且 FP 结果只是一个近似值,因此 不正确 .

但是,如果你只需要一个不精确的双精度值,我建议:

1/ 使用更简单的公式,例如斯特林公式。 https://en.wikipedia.org/wiki/Stirling%27s_approximation#Speed_of_convergence_and_error_estimates 如果你在斯特林级数中保留 4 或 5 个数字,则由于使用此公式而导致的近似损失不会大于由于尾数有限而造成的近似损失。 (而且会快很多)。

2/不管你用的是阶乘还是斯特林,你都可以用一个技巧来扩展double中的指数。这个想法只是为了将指数保持在 2^512 以下,并且在每次 mult 之后,您进行以下检查

 int extra_exponent=0;
 double theshold = 2^512;
 double threshold_inv=2^-512;
 ....
 # check exponent on n
 if (n>threshold) {
   n *= threshold_inv ; # reduce exponent
   extra_exponent++ ; # but keep track of it
 }

只要乘以 < 2^512 的数字, long 永远不会溢出。最后,要获得 "real" 值,您必须乘以 2^(extra*512) (这可能不是那么简单)。并且您的精度受尾数大小的限制。

但最好的建议是使用无限精度的算法。这是获得准确结果的唯一方法。