12

Fortran 对我来说是全新的,有人可以帮我解决以下问题吗?我想在我的电脑上找出所有整数种类数以及每个种类数的最大值和最小值。我在下面列出了代码:

program intkind
implicit none

integer :: n=1
integer :: integer_range =1


do while(integer_range /= -1)
    print*, "kind_number ", selected_int_kind(n)
    call rang(integer_range)
    n = n *2
    integer_range = selected_int_kind(n)
end do

contains
subroutine rang(largest) 
    integer largest
    print*, huge(largest)

end subroutine

end 

我得到的整数种类数是:1,2,4,8。

  1. 为什么每个种类数的每个最大整数都相同:2147483647?最小整数是否有内在函数?

  2. 调用子程序时如何保留整数种类编号rang?我认为这是最大整数的关键。

4

2 回答 2

18

你的子程序:

subroutine rang(largest) 
    integer :: largest
    print *, huge(largest)
end subroutine

将默认大小的整数作为输入,并打印适合该默认大小的整数的最大可能值。它总是返回巨大的(默认整数),在大多数系统上,巨大的(4 字节整数)或 2147483647。 huge只考虑变量类型;它不会以任何方式解释变量。您可以执行上述操作的唯一方法是使用参数化派生类型,这些派生类型足够新,以至于在编译器中对它的支持仍然有点参差不齐。

如果您想查看不同种类的 INTEGER 的范围,则必须使用不同的变量:

program integerkinds
    use iso_fortran_env
    implicit none

    integer :: i
    integer(kind=int8)  :: i8
    integer(kind=int16) :: i16
    integer(kind=int32) :: i32
    integer(kind=int64) :: i64

    integer(kind=selected_int_kind(6)) :: j6
    integer(kind=selected_int_kind(15)):: j15

    print *,'Default:'
    print *, huge(i)
    print *,'Int8:'
    print *, huge(i8)
    print *,'Int16:'
    print *, huge(i16)
    print *,'Int32:'
    print *, huge(i32)
    print *,'Int64:'
    print *, huge(i64)

    print *,''

    print *,'Selected Integer Kind 6:'
    print *, huge(j6)

    print *,'Selected Integer Kind 15:'
    print *, huge(j15)

end program integerkinds

运行给出:

$ ./intkinds
 Default:
  2147483647
 Int8:
  127
 Int16:
  32767
 Int32:
  2147483647
 Int64:
  9223372036854775807

 Selected Integer Kind 6:
  2147483647
 Selected Integer Kind 15:
  9223372036854775807
于 2012-03-05T16:10:37.517 回答
-7

纯粹作为附录或替代观点,Fortran 变量是根据分配给 var 的内存字节数定义的。实际上,所有可比较的编译器都根据分配的字节来定义变量,否则系统将很难在内存中分配/存储,并且如果没有这些,则非常难以执行算术等。

对于像我这样的一些人来说,使用稍旧的符号(而不是“kind konfusion”)更容易看到发生了什么。特别是,很多编译器提供了 Kind 和 bytes/var 之间的直接 1:1 对应关系,这使得最大/最小整数的计算相当简单(一些编译器使用非线性或非直接对应)。虽然一定要注意最后的可移植性帮助。例如

Integer(1)      :: Int1     ! corresponds to  a 1 byte integer
Integer(2)      :: Int1     ! corresponds to  a 2 byte integer
Integer(4)      :: Int1     ! corresponds to  a 4 byte integer
Integer(8)      :: Int1     ! corresponds to  an 8 byte integer

类似的符号适用于其他 Fortran 类型(Real、Logical 等)。如果未指定“大小”,则所有 var 类型都分配了默认的字节数。

特定类型的最大字节数还取决于编译器和系统(例如,Integer(16) 并非在所有系统上都可用,等等)。

一个字节是 8 位,所以如果从 1 开始编号,单个字节应该能够容纳 2^8 = 256 的最大值,或者从 0 开始时 = 255。

但是,在 Fortran 中,(几乎所有)数字变量都是“有符号的”。这意味着在位表示中的某处需要一位来跟踪该数字是 +ve 数字还是 -ve 数字。因此,在本例中,最大值为 2^7,因为“符号”信息的一位“丢失/保留”。因此,带符号的 1 字节整数的可能值为 -127:+128(注意 Abs(limits) 总和为 255,因为“0”占据了一个位置,总共 256 个“事物”,因为它应该是)。

类似的规则适用于所有此类变量,只是指数“n”,在 2^n 中,根据字节数而变化。例如,一个 Integer(8) var 有 8 个字节或 64 位,其中 1 位丢失/保留用于符号信息,因此如果从 1 开始编号,则最大可能值为 2^63 = 9223372036854775808,或者在开始时 = 4611686018427387904从 0。

标准整数数据模型将被概括为:

IntNum = s * Sum[ w(k) * 2 ^ (k-1), k=1:(NumBytes*8)-1], 

其中 s = "sign" (+/-1),对于第 k 位值,w(k) 为 1 或 0。

不需要在类型声明中使用显式数字或环境变量;允许使用用户定义的编译时间常数(即参数)。例如

Integer, Parameter        :: DP = Kind(1.0d0)    ! a standard Double Precision/8-byte declaration
Integer, Parameter        :: I4B = 4             ! NOTICE, here the "Integer" bit has not been explicitly "sized", so defaults to "Integer(4)"
!
Real(DP)                  :: ADoublePrecReal     ! an 8-byte Real (approx 15 decimal places with exp +/- approx 300, see Real data model)
!
Integer(I4B)              :: AStandardInt        ! a 4-byte integer.

由于 Parameter 语句可以在另一个通过 Use 等访问的模块中,重新编译大型复杂代码以获得所需的“精度”的替代定义是一件简单的事情。例如,如果将 DP 编辑为 Kind(1.0),则应用该声明的任何地方都将变为“单精度”Real。

Fortran 内在函数 Huge()、Tiny() 等有助于确定给定系统上的可能性。

Fortran“位”内在函数和其他工具/方法可以完成更多工作。

于 2014-08-13T00:25:03.703 回答