如何在 Fortran 中处理大整数? [英] How do I do big integers in Fortran?
问题描述
我需要生成一些大整数.请参见下面的示例.
I need to generate some big integers. See example below.
Input Result
40 165580141
80 37889062373143906
120 8670007398507948658051921
160 1983924214061919432247806074196061
200 453973694165307953197296969697410619233826
这是我的 Fortran 代码:
Here is my Fortran code:
program cycle
use iso_fortran_env
implicit none
character(200) :: str
integer :: n
integer(kind=int64) :: x1, result, x2, x3
do n = 40, 500, 40
x1 = n
result = 1
x2 = 0
x3 = 1
do
if (x1 > 1) then
x2 = result
result = result + x3
x3 = x2
x1 = x1 - 1
else
exit
end if
end do
write(str,'(i64)') result
print *, n, adjustl(str)
end do
end program cycle
这是示例输出:
40 165580141
80 37889062373143906
120 790376311979428689
160 9217463444206948445
200 3721511182311577122
如您所见,它正确获取了前两个数字,但其余数字超出了 64 位整数的范围.我看过其他问题(1)但我真的很感兴趣简单的方法,最好内置在语言本身中.在 Ruby 和 Go 中,我几乎没有遇到什么麻烦.我是否忽略了 Fortran 中明显的东西?我可以在我的代码中使用更好的选择吗?
As you can see, it gets the first two numbers right but the rest are beyond the reach of 64 bit integers. I've looked at other questions (1) but I'm really interested in a simple way, preferably built into the language itself. In Ruby and Go I have little trouble. Am I overlooking something obvious in Fortran? Is there a better option I can use in my code?
推荐答案
没有内置的大数"支持,但我们可以先检查是否有更大的整数类型可用(如上面的 Francescalus 和许多以前的页面(例如此页面).在我的gfortran-6.1计算机上,编译器似乎支持 128 位整数类型,所以我可以计算出 n=160 左右的结果.
There is no built-in "big number" support, but we can first check whether there is a larger integer kind available (as mentioned by Francescalus above and also many previous pages (e.g. this page). On my computer with gfortran-6.1, the compiler seems to support 128-bit integer kind, so I could calculate the result up to n=160 or so.
program cycle
...
integer, parameter :: verylong = selected_int_kind(32)
integer(verylong) :: x1, result, x2, x3
print *, "int32 = ", int32 !! from iso_fortran_env
print *, "int64 = ", int64
print *
print *, "kind..(16) => ", selected_int_kind(16) !! 8
print *, "kind..(32) => ", selected_int_kind(32) !! 16
print *, "kind..(40) => ", selected_int_kind(40) !! -1 (not available)
print *, "kind..(64) => ", selected_int_kind(64) !! -1 (not available)
print *
print *, "sizeof(x1) = ", sizeof(x1), "(bytes)" !! GNU extension
print *, "storage_size(x1) = ", storage_size(x1), "(bits)" !! F2008
print *, "huge(x1) = ", huge(x1) !! largest integer
...
结果:
int32 = 4
int64 = 8
kind..(16) => 8
kind..(32) => 16
kind..(40) => -1
kind..(64) => -1
sizeof(x1) = 16 (bytes)
storage_size(x1) = 128 (bits)
huge(x1) = 170141183460469231731687303715884105727
n= 40 res= 165580141
n= 80 res= 37889062373143906
n= 120 res= 8670007398507948658051921
n= 160 res= 1983924214061919432247806074196061
n= 200 res= 37016692776042937155243383431825151522
n= 240 res= -159769225356713774587328406036589956191
...
<小时>
虽然没有内置的BigInt"类型,但使用外部库相当简单(例如,fmlib链接自此页面).由于各种运算符和赋值都是重载的,因此几乎不需要对您的代码进行任何修改.
While there is no built-in "BigInt" type, it is rather straightforward to use an external library (for example, fmlib linked from this page). Since various operators and assignment are overloaded, almost no modifications are necessary to your codes.
程序:
1) 下载文件 FMfiles.zip 并解压 FM.95
、FMZM90.f95
和 FMSAVE.f95
1) Download the file FMfiles.zip and extract FM.95
, FMZM90.f95
, and FMSAVE.f95
2) 将库文件设为
gfortran -c -O2 FMSAVE.f95 FMZM90.f95 FM.f95
ar rv fmlib.a FM*.o
3) 修改你的代码如下(修改的部分用箭头标记).
3) Modify your code as follows (the modified parts are marked with arrows).
program cycle
use FMZM !<----- a module for handling big numbers
implicit none
character(200) :: str
integer :: n
type(IM) :: x1, result, x2, x3 !<----- IM = BigInt, FM = BigFloat
do n = 40, 500, 40
x1 = n
result = 1
x2 = 0
x3 = 1
do
if (x1 > 1) then
x2 = result
result = result + x3
x3 = x2
x1 = x1 - 1
else
exit
end if
end do
str = IM_format( 'i200', result ) !<----- convert BigInt to string
print *, n, trim( adjustl(str) ) !<----- print huge integers
end do
end program cycle
4)编译(假设test.f90"是上面的代码):
4) Compile (assuming that "test.f90" is the above code):
gfortran test.f90 fmlib.a
./a.out
5) 结果
n result
40 165580141
80 37889062373143906
120 8670007398507948658051921
160 1983924214061919432247806074196061
200 453973694165307953197296969697410619233826
240 103881042195729914708510518382775401680142036775841
280 23770696554372451866815101694984845480039225387896643963981
320 5439356428629292972296177350244602806380313370817060034433662955746
360 1244666864935793005828156005589143096022236302705537193166716344690085611761
400 284812298108489611757988937681460995615380088782304890986477195645969271404032323901
440 65172495098135102433647404982700073500075401759827878315356483347951218369680224170989749666
480 14913169640232740127827512057302148063648650711209401966150219926546779697987984279570098768737999681
我们可以通过注意 n
的 result
实际上等于 fibonacci(n+1),例如我们有 fibonacci(481) for n = 480
.
We can verify the result by noting that result
for n
is actually equal to fibonacci(n+1), so for example we have fibonacci(481) for n = 480
.
这篇关于如何在 Fortran 中处理大整数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!