FORTRAN 95大数除法的精度
我编写了一个子程序来计算二项式系数(n选择k),它将用于n的大值和k的中等值(因此接近给定n的最大值)。子程序代码为FORTRAN 95大数除法的精度,fortran,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) temp
!
! 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
顺便说一句:kind=16是我机器上的四精度
谢谢根据您使用的整数的大小,可能有在您的系统上使用扩展精度整数的便携式方法。标准模块ISO_FORTRAN_ENV应该定义一些整数类型(INT8、INT16、INT32、INT64等),从FORTRAN 2008开始,这些类型包含在数组整数类型中,但目前这种类型的实现似乎参差不齐 如果你仍然没有足够的空间,你有两个选择:重新设计你的问题,使其在你的精度范围内工作,或者寻找一个扩展的或任意精度的数学库。令人高兴的是,LBNL在下面列出了许多这样的库 更新:
selected\u int\u kind
是创建扩展精度值的另一种动态方法,但您仍然需要知道编译器接受哪些“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\u int\u type
获得一些额外的精度,但它会随着硬件和编译器的不同而有所不同,根据问题的不同,可能会给您提供足够的精度。您使用的编译器是什么?我得到了61448471214136179596720592960.0000
这是一个预期的答案。小数出现是因为cmb
是实的。您得到的是由于浮点计算而导致的错误。谢谢您的回答。我使用的是Absolft FORTRAN 95。如果我将cmb声明为整数,则它根本不起作用。有什么我可以做的错误,由于浮点计算?我没有它,使用英特尔的。它还可能取决于x86或x64 OS/CPU。如果您有x64编译器和系统-为什么不使用selected\u int\u kind(32)
如果您关心精确的数字精度,请不要使用不可移植的kind=16
,以指定四倍精度,而是使用许多其他可移植方式。它已经在这里重复了一百万次。即使real*16
在我看来也更好,但最好是使用具有工作精度的命名常量,这很容易更改。在这种情况下,请尝试使用Cheery建议的最大整数类型。我大体上同意你的看法,但在这种情况下需要int128
,并且它不是由ISO_FORTRAN_ENV定义的,尽管128位整数实际上在某些编译器中可用。这就是为什么我更喜欢注释中已经建议的selected_int_kind
,而不是这个问题的ISO_FORTRAN_ENV kind常量。这种方法的一个问题是,您需要知道哪些种类值可以作为selected_int_kind
的参数;我会通过更新我的回答来澄清这一点什么?您只需提供所需的位数,如果您得到它,则为。很简单,只需数一数问题中的数字。也许,也许不是。看上面,当然!它不是动态的,它是完全静态的!关键是你可能会从中得到可用的类型,但是你肯定不会从iso\u fortran\u env
命名常量中得到它(还有其他方法)。我从来没有说过你可以保证从选定的类型中获得所需的类型,这就是为什么我在前面的评论中写道,你需要看看你是否可以获得它,以及为什么我在第一篇评论中写道它在某些编译器中可用。