我正在使用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的阶乘?
答案 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)(可能并不那么简单)。而您的精度受尾数大小的限制。
但是最好的建议是使用无限精度算法。这是获得精确结果的唯一方法。