Fortran: the largest and the smallest integer
Asked Answered
L

2

12

Fortran is completely new for me, can anybody help me to solve the follwing problem? I want to find out all the integer kind numbers and the largest and the smallest value for each kind number on my pc. I have code listed below:

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 

The integer kind numbers what I get are : 1,2,4,8.

  1. Why is each largest integer for each kind number the same: 2147483647? And is there a intrinsic function for the smallest integer?

  2. How can I keep the integer kind number when the subroutine rang is called? I think it is the key to the largest integer.

Laurasia answered 5/3, 2012 at 15:58 Comment(1)
Just for someone coming upon this much later. While there is no intrinsic, you can always use -huge(n) to compute the smallest integer available.Bastien
A
20

Your subroutine:

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

takes as input a default-sized integer, and prints the largest possible value that will fit in that default-sized integer. It will always return huge(default integer) which is, on most systems, huge(4-byte-integer), or 2147483647. huge considers only the variable type; it doesn't interpret the variable in any way. The only way you could do what you're trying to do above is with parameterized derived types, which are new enough that support for it in compilers is still a little spotty.

If you want to take a look at ranges of different KINDs of INTEGERs, you'll have to use different variables:

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

Running gives:

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

 Selected Integer Kind 6:
  2147483647
 Selected Integer Kind 15:
  9223372036854775807
Allstar answered 5/3, 2012 at 16:10 Comment(2)
IF: selected_int_kind(9) = 4 ,integer(kind=selected_int_kind(9)) :: j4 and huge(j4) is:2147483647 on my pc. the definition of selected_int_kind(r) says that it can represent alle integer values n in the range -10r < n > 10r. IF r =9, then the largest value is 10**9-1,it is less than 2147483647(huge(j4)),why? I cannot anderstand it.Laurasia
First part: yes, huge(j4) should be 2147483647, because j4 is defined to be integer(kind=selected_int_kind(9)). But note that you had to define j4 to be of that kind. You can't just change kinds after the variables have been defined; eg, you can call selected_int_kind() as many times as you want afterwards and it doesn't change anything. The example above shows you how to define types of the various kinds.Allstar
C
-10

Purely as an addendum, or alternate perspective, Fortran variables are defined in terms of the number of bytes of memory allocated to the var. Indeed, all comparable compilers define vars in terms of bytes allocated, otherwise it would be very difficult for the system to allocate/store in memory, and very very difficult to perform arithmetic etc without such.

For some, like me, it is easier to see what is going on by using a slightly older notation (rather than the "kind konfusion". In particular, very many compilers provide a direct 1:1 correspondence between Kind and bytes/var, which then makes calculation of largest/smallest Integer fairly straightforward (some compiler use a non-linear or non-direct correspondence). Though be sure to take note of the portability assistance at the end. For example

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

Similar notation applies to other Fortran types (Real, Logical, etc). All var types have a default number of bytes allocated if the "size" is not specified.

The maximum number of bytes for a particular type also depends on compiler and system (e.g. Integer(16) is not available on all systems, etc).

A byte is 8 bits, so a single byte should be able to accommodate the largest value of 2^8 = 256 if numbering from 1, or = 255, when starting from 0.

However, in Fortran, (almost all) numeric vars are "signed". That means somewhere in the bit representation one bit is required to track whether the number is a +ve number or a -ve number. So in this example, the max would be 2^7, since one bit is "lost/reserved" for the "sign" information. Thus, the values possible for a signed 1-byte integer are -127:+128 (notice the Abs(limits) sum to 255, since "0" takes up one place, for a total of 256 "things", as it should be).

A similar rule applies for all such vars, with simply the exponent "n", in 2^n, varying based on the number of bytes. For example, an Integer(8) var has 8 bytes, or 64 bits, with 1 bit lost/reserved for sign information, so the largest possible value would be 2^63 = 9223372036854775808, if numbering from 1, or = 4611686018427387904 when starting from 0.

The standard Integer data model would be generalised as:

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

where s = "sign" (+/-1), w(k) is either 1 or 0 for the kth bit value.

One need not use explicit numbers or env vars in the type declarations; user defined compile time constants (i.e. Parameters) are permitted. For example

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.

Since the Parameter statement can be in another Module accessible via Use etc, it is a simple matter to recompile large complex code for alternate definitions of "precision" desired. For example, if DP is edited to Kind(1.0), then everywhere that declaration is applied will become "single precision" Real.

The Fortran intrinsic functions Huge(), Tiny() etc help to determine what is possible on a given system.

Much more can be accomplished with Fortran "bit" intrinsics, and other tools/methods.

Cunha answered 13/8, 2014 at 0:25 Comment(7)
This answer starts off wrong: Fortran variables are not defined in terms of the number of bytes they occupy. The kind selectors, the integers in an expression such as integer(8) or real(4), simply identify one of the kinds supported by the compiler. The NAG Fortran compiler, for example, defaults to integer(2) for 4-byte integers and integer(3) for 8-byte integers. It is common for compilers to use kind selectors which match the number of bytes used, but it is not required by the standard.Arlindaarline
This is a common misconception. See also #3170739Morven
Yes, each compiler vendor can do what ever they like, and often do. And yes, it would have helped to have more than one emphasise on the variance between systems (apparently, once is not enough for some). Still, the original comments made are correct for compilers from Compaq, DEC, IBM, CRAY, Oracle, Intel, etc etc., with the kind/bytes corresponding exactly as is. I had also emphasised the use of global Parameters for Kind as good practice for the same reasons that others only cite after wards. Also, it is quite certain that the Integer Data model formulation is correct, check any book ..Cunha
You've now edited your answer but it still states that Fortran variables are defined in terms of the number of bytes of memory allocated to the var. They may be, but there is no requirement that they must be. Fortran has been implemented on machines for which a byte would have been an alien concept, and I have no doubt that it will again, in future, be implemented on such machines.Arlindaarline
You are also incorrect to state that double precision reals are necessarily 8 bytes. The latest standard requires that a double precision real have more precision than a default real, and that it have at least 10 decimal digits of precision and an exponent range of +/- 37. But the standard is silent on how a processor (to use the language of the standard) is to provide this precision. I think that all the current crop of Fortran compiler do implement double precision reals in 8 bytes but that's just a snapshot at one moment in the language's long history and longer future.Arlindaarline
It actually states exactly the opposite, and I go do some length to ensure there is no misunderstanding of "DP", "Double Precision", etc. I particularly suggest that user defined Parameters are used to declare Kind ... precisely to avoid the problem you raise. For example, in the "bad old days" in the 70's-90's, code that actually used the declaration "Double Precision" on "normal" machines (e.g. IBM 3033) meant Real*8, but on running on, say, a Cray-YMP, that machine interpreted "Double Precision" as Real*16. Hence my extra effort ... no idea how you got another idea.Cunha
Also, this particular thread's object was discussing largest Integer. I appreciate the digression on to other topics, and I went to some lengths to emphasise exceptions. While you are quite correct to note exceptions, one cannot be expected to submit an tome covering all possibilities ... I must say, your comments do seem a little vexatious and a blurring of key issue. I presume you will wish to have the "last word", so go ahead, I wont respond.Cunha

© 2022 - 2024 — McMap. All rights reserved.