对大整数求幂时得到错误的结果

时间:2019-06-14 19:51:45

标签: fortran

我尝试在fortran中计算97 ^ 5,并将精度扩展到18个有效数字。当我对97和5使用整数类型时,结果为-2594335,这显然是错误的。我知道在将任何一个数字更改为实数后,都可以解决此问题并产生正确的数学答案。但是,我很好奇,当两个数字都作为整数输入时,整数算法中的哪些细节会导致错误的计算结果。

integer,parameter :: ikind=selected_real_kind(p=18)
real(kind=ikind) :: x,y
print *, 97**5
print *, 97.**5

第一行的输出为-2594335,第二行的输出为8.58734029E + 09,是正确的。

2 个答案:

答案 0 :(得分:0)

这是 integer overflow 的示例。您的系统使用的是4字节整数,可以存储[-2^31, 2^31-1] = [-2147483648 to 2147483647]范围内的值(数字31位,符号1位)。由于97^5的值超出此范围,因此将仅保留最低有效位。

当我在Python(使用无界整数)中执行此计算时,我得到了

>>> (97**5)%(2**32)
4292372961
>>> (97**5)%(2**32) - 2**32
-2594335

我在第二行减去2^32以返回到允许值的范围。

答案 1 :(得分:0)

浏览代码:

integer,parameter :: ikind=selected_real_kind(p=18)
real(kind=ikind) :: x,y

xy现在定义为real(kind=ikind)。在我的机器上,ikind等于10,并且导致幂4932的最大值(huge(x))约为10。这都是无用的,因为您以后不会使用这些变量。

print *, 97**5

这意味着“默认整数97”为幂“默认整数5”。对于32位整数,结果(使用wht提到的溢出算法)就是您得到的结果。

print *, 97.**5

这表示“默认实数97”为幂“默认整数5”。对于32位实数,结果是正确的,因为它保持在32位实数的可计算范围内。

TL; DR:在Fortran中

  • “ 97”是“值97的默认整数种类”
  • “ 97。”是“默认实型值97”

要使用精度更高的文字常量,请使用例如

integer,parameter :: rk = selected_real_kind(p=14)
real(kind=rk) :: x

x = 97_rk

(这对于精确的整数是没有用的,因为它们将被正确地转换。对于不能以较低的精度精确表示的值,这很重要)。

相关问题