如何在 Fortran 中处理大整数? [英] How do I do big integers in Fortran?

查看:24
本文介绍了如何在 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.95FMZM90.f95FMSAVE.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

我们可以通过注意 nresult 实际上等于 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆