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

时间:2019-01-11 18:19:49

标签: assembly floating-point double mips factorial

我正在使用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的阶乘?

1 个答案:

答案 0 :(得分:6)

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

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

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

2 /无论您使用阶乘还是斯特林,都可以使用技巧来扩展双精度指数。只是将指数保持在2 ^ 512以下,并且在每次多次运算之后,您都需要进行以下检查

 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,就永远不会溢出。最后,要获得“真实”值,您必须乘以2 ^(extra * 512)(可能并不那么简单)。而您的精度受尾数大小的限制。

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