FORTRAN 95精度非常大的分割

时间:2014-10-11 01:07:35

标签: fortran

我写了一个子程序来计算二项式系数(n选择k),它将用于n的大值和k的中等值(因此接近给定n的最大值)。子程序代码是

!
!   Subroutine to calculate combinatoric term (n choose x)
!
subroutine COMBO(m,y,combin)
implicit none
integer m,y,b1,b2,maxx,minn
real (kind=16) combin,temp1,temp2
temp1 = real(1,16)
temp2 = real(1,16)
maxx = MAX(y,m-y)
minn = MIN(y,m-y)
do b1 = maxx+1,m
temp1 = temp1*real(b1,16)
enddo
do b2 = 1,minn
temp2 = temp2*real(b2,16)
enddo
combin = temp1/temp2
end subroutine COMBO

适用于中等大小的值。但是,如果我使用n = 100和k = 55,我得到以下

61448471214136179596720592959.998

小数部分显然是错误的,因为组合总是整数。主程序是

program chkint
implicit none
integer i,j,n,k
real (kind=16) cmb

print*,"what is n?"
read*,n
print*,"what is k?"
read*,k

call combo(n,k,cmb)
print*,cmb

end

BTW:kind = 16是我机器上的四倍精度。

由于

1 个答案:

答案 0 :(得分:1)

根据您使用的整数的大小,可能有便携式方法在您的系统上使用扩展精度整数。标准模块ISO_FORTRAN_ENV应该定义许多整数种类(INT8,INT16,INT32,INT64等)。从Fortran 2008开始,它们包含在数组INTEGER_KINDS中,但目前这种实现看起来很不稳定。

如果你仍然没有空间,你有两个选择:根据你的精确度重新设计你的问题,或寻找扩展或任意精度的数学库。令人高兴的是,LBNL在http://crd-legacy.lbl.gov/~dhbailey/mpdist/

下列出了一些此类库

<强> 更新

selected_int_kind是创建扩展精度值的替代动态方法,但您仍需要知道编译器接受哪些“类型”值。例如:

program kind_int
    use iso_fortran_env, only: output_unit, INT8, INT16, INT32, INT64!, &
!        INTEGER_KINDS

    implicit none

    integer :: i

1   format(A)
2   format('Kind name = ', A5, T20, 'kind value = ',I2,                &
        T40, 'maximum = ', I19)
3   format('Available kind values: ', I2, *(', ', I2))
    continue

    write(output_unit, 1) 'Maximum value of supported integer kinds:'
    write(output_unit, 2) 'INT8 ', INT8,  huge(1_INT8)
    write(output_unit, 2) 'INT16', INT16, huge(1_INT16)
    write(output_unit, 2) 'INT32', INT32, huge(1_INT32)
    write(output_unit, 2) 'INT64', INT64, huge(1_INT64)
    write(output_unit, 2) '16   ', 16, huge(selected_int_kind(16))
    write(output_unit, 2) '32   ', 32, huge(selected_int_kind(32))

!    write(output_unit, 3) INTEGER_KINDS

    stop
end program kind_int

在linux64系统上使用gfortran提供以下内容:

Maximum value of supported integer kinds:
Kind name = INT8   kind value =  1     maximum =                                      127
Kind name = INT16  kind value =  2     maximum =                                    32767
Kind name = INT32  kind value =  4     maximum =                               2147483647
Kind name = INT64  kind value =  8     maximum =                      9223372036854775807
Kind name = ik32   kind value = 16     maximum =  170141183460469231731687303715884105727
Kind name = ikxx   kind value = 16     maximum =  170141183460469231731687303715884105727

Selected int kind value =  1           kind value =    1
Selected int kind value =  2           kind value =    1
Selected int kind value =  3           kind value =    2
Selected int kind value =  4           kind value =    2
Selected int kind value =  5           kind value =    4
Selected int kind value =  6           kind value =    4
Selected int kind value =  7           kind value =    4
Selected int kind value =  8           kind value =    4
Selected int kind value =  9           kind value =    4
Selected int kind value = 10           kind value =    8
Selected int kind value = 11           kind value =    8
Selected int kind value = 12           kind value =    8
Selected int kind value = 13           kind value =    8
Selected int kind value = 14           kind value =    8
Selected int kind value = 15           kind value =    8
Selected int kind value = 16           kind value =    8
Selected int kind value = 17           kind value =    8
Selected int kind value = 18           kind value =    8
Selected int kind value = 19           kind value =   16
Selected int kind value = 20           kind value =   16
Selected int kind value = 21           kind value =   16
Selected int kind value = 22           kind value =   16
Selected int kind value = 23           kind value =   16
Selected int kind value = 24           kind value =   16
Selected int kind value = 25           kind value =   16
Selected int kind value = 26           kind value =   16
Selected int kind value = 27           kind value =   16
Selected int kind value = 28           kind value =   16
Selected int kind value = 29           kind value =   16
Selected int kind value = 30           kind value =   16
Selected int kind value = 31           kind value =   16
Selected int kind value = 32           kind value =   16
Selected int kind value = 33           kind value =   16
Selected int kind value = 34           kind value =   16
Selected int kind value = 35           kind value =   16
Selected int kind value = 36           kind value =   16
Selected int kind value = 37           kind value =   16
Selected int kind value = 38           kind value =   16
Selected int kind value = 39           kind value =   -1

通过稍加修改,程序在同一系统上使用ifort生成以下内容:

Maximum value of supported integer kinds:
Kind name = INT8   kind value =  1     maximum =                                      127
Kind name = INT16  kind value =  2     maximum =                                    32767
Kind name = INT32  kind value =  4     maximum =                               2147483647
Kind name = INT64  kind value =  8     maximum =                      9223372036854775807

Selected int kind value =  1           kind value =    1
Selected int kind value =  2           kind value =    1
Selected int kind value =  3           kind value =    2
Selected int kind value =  4           kind value =    2
Selected int kind value =  5           kind value =    4
Selected int kind value =  6           kind value =    4
Selected int kind value =  7           kind value =    4
Selected int kind value =  8           kind value =    4
Selected int kind value =  9           kind value =    4
Selected int kind value = 10           kind value =    8
Selected int kind value = 11           kind value =    8
Selected int kind value = 12           kind value =    8
Selected int kind value = 13           kind value =    8
Selected int kind value = 14           kind value =    8
Selected int kind value = 15           kind value =    8
Selected int kind value = 16           kind value =    8
Selected int kind value = 17           kind value =    8
Selected int kind value = 18           kind value =    8
Selected int kind value = 19           kind value =   -1

正如Vladimir F建议的那样,使用selected_int_type可以获得一些额外的精度,但它会因硬件和编译器的不同而有所不同,根据问题可能会给出足够的精度。