4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Fortran INTERGER*16 の最大値

Last updated at Posted at 2018-11-07

Fortran の INTEGER*16 の最大値はいくつ?と思ったので調べてみた。

Integer には bit 演算が使えるので全ビットを 1にした後に、符号ビットを落とせば良さそう。

Max_Integer.f90
      PROGRAM Max_Integer
      IMPLICIT NONE
      INTEGER*16 Imax

      Imax = IEOR(Imax, Imax)   ! Imax = Imax xor Imax → 0
      Imax = NOT(Imax)          ! Imax の全ビットを立てる
      Imax = ISHFT(Imax,-1)     ! 右シフトして、最上位ビットを落とす
      WRITE (*,*), "NOT, ISHFT(-1):", Imax

      Imax = Imax +1            ! 最大であることを確認するために +1 してみる
      WRITE (*,*), "NOT, ISHFT(-1) +1:", Imax

      END

下のは間違ってないことを確認のため +1。
gcc の Fortran でコンパイル

tcsh
% gfortran Max_Integer.f90 && ./a.out
 NOT, ISHFT(-1): 170141183460469231731687303715884105727
 NOT, ISHFT(-1) +1: -170141183460469231731687303715884105728

なんか、書式が古いとかワーニングが出ましたが、それは無視
ほぅ、これは声に出して読みたくないですね。最大値のついでに最小値も見えました。浮動小数点には使えない方法なのは残念。
一時間ぐらいかかりましたができるもんですね。

ちなみに INTEGER*16 の宣言は INTEGER(kind=16) でも良いようです。

↓コンパイルした環境は MSYS2 の gcc 8.2.0 でした

the_GNU_Compiler_Collection
% gfortran --version
GNU Fortran (Rev3, Built by MSYS2 project) 8.2.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% uname -a
MINGW64_NT-10.0 H97-PRO 2.11.1(0.329/5/3) 2018-09-10 14:19 x86_64 Msys

ついでなので

Max_Integer.f90
% cat Max_Integer.f90
      PROGRAM Max_Integer
      IMPLICIT NONE
      INTEGER(kind=8) Imax

      Imax = IEOR(Imax, Imax)   ! Imax = Imax xor Imax → 0
      Imax = NOT(Imax)          ! Imax の全ビットを立てる
      Imax = ISHFT(Imax,-1)     ! 右シフトして、最上位ビットを落とす
      WRITE (*,*), "NOT, ISHFT(-1):", Imax

      Imax = Imax +1            ! 最大であることを確認するために +1 してみる
      WRITE (*,*), "NOT, ISHFT(-1) +1:", Imax

      END
% gfortran Max_Integer.f90 && ./a.exe
Max_Integer.f90:8:17:

       WRITE (*,*), "NOT, ISHFT(-1):", Imax
                 1
Warning: Legacy Extension: Comma before i/o item list at (1)
Max_Integer.f90:11:17:

       WRITE (*,*), "NOT, ISHFT(-1) +1:", Imax
                 1
Warning: Legacy Extension: Comma before i/o item list at (1)
 NOT, ISHFT(-1):  9223372036854775807
 NOT, ISHFT(-1) +1: -9223372036854775808

豆知識:bit 演算で、ローテートというと、はみ出した bit が反対側の bit になって表れる演算のこと。シフトは、はみ出した bit は捨てて、反対側の bit が 0 になる演算のことです。

cure_honeyさんのコメントを見てなるほどー、と思い はじめての Fortran90 (PDFファイル) というのを見つけたのでテスト。

Max_Integer.f90
      PROGRAM Max_Integer
      IMPLICIT NONE
      CHARACTER IFMT*12
      CHARACTER EFMT*12
      CHARACTER Lentest*1000
      CHARACTER ExpLentest*100

      INTEGER I
      INTEGER(kind=1) I1
      INTEGER(kind=2) I2
      INTEGER(kind=4) I4
      INTEGER(kind=8) I8
      INTEGER(kind=16) I16
      REAL R
      REAL(kind=4) R4
      REAL(kind=8) R8
      REAL(kind=16) R16

      IFMT = '(A I00)'     ! 整数用の書式
      EFMT = '(A G00.00)'  ! 実数用の書式
      PRINT "(A)",    "=== Int ==="
      PRINT IFMT, "KIND     : ", KIND(I)
      
      WRITE (IFMT(5:6), '(I0.2)') RANGE(I1) + 1
      PRINT "(A)",  "=== Int1 ==="
      PRINT IFMT,  "KIND     :", KIND(I1)
      PRINT IFMT,  "HUGE     :", HUGE(I1)
      PRINT IFMT,  "RANGE    :", RANGE(I1)
      PRINT IFMT,  "BIT_SIZE :", BIT_SIZE(I1)
      
      WRITE (IFMT(5:6), '(I0.2)') RANGE(I2) + 1
      PRINT "(A)",  "=== Int2 ==="
      PRINT IFMT,  "KIND     :", KIND(I2)
      PRINT IFMT,  "HUGE     :", HUGE(I2)
      PRINT IFMT,  "RANGE    :", RANGE(I2)
      PRINT IFMT,  "BIT_SIZE :", BIT_SIZE(I2)
      
      WRITE (IFMT(5:6), '(I0.2)') RANGE(I4) + 1
      PRINT "(A)",  "=== Int4 ==="
      PRINT IFMT,  "KIND     :", KIND(I4)
      PRINT IFMT,  "HUGE     :", HUGE(I4)
      PRINT IFMT,  "RANGE    :", RANGE(I4)
      PRINT IFMT,  "BIT_SIZE :", BIT_SIZE(I4)
      
      WRITE (IFMT(5:6), '(I0.2)') RANGE(I8) + 1
      PRINT "(A)",  "=== Int8 ==="
      PRINT IFMT,  "KIND     :", KIND(I8)
      PRINT IFMT,  "HUGE     :", HUGE(I8)
      PRINT IFMT,  "RANGE    :", RANGE(I8)
      PRINT IFMT,  "BIT_SIZE :", BIT_SIZE(I8)
      
      WRITE (IFMT(5:6), '(I0.2)') RANGE(I16) + 1
      PRINT "(A)",  "=== Int16 ==="
      PRINT IFMT,  "KIND     :", KIND(I16)
      PRINT IFMT,  "HUGE     :", HUGE(I16)
      PRINT IFMT,  "RANGE    :", RANGE(I16)
      PRINT IFMT,  "BIT_SIZE :", BIT_SIZE(I16)
      
      PRINT "(A)",  "============="
      PRINT "(A)",  "=== Real  ==="
      WRITE (Lentest, '(G0)') HUGE(R)
      WRITE (IFMT,1000) LEN_TRIM(Lentest)

      PRINT IFMT,  "KIND      :", KIND(R)

      PRINT "(A)",  "=== Real4 ==="
      WRITE (Lentest, '(G0)') HUGE(R4)
      WRITE (ExpLentest, '(G0)') RANGE(R4)
      WRITE (IFMT,1000) LEN_TRIM(Lentest)
      WRITE (EFMT,2000) LEN_TRIM(Lentest) - LEN_TRIM(ExpLentest) - 4

      PRINT IFMT,  "KIND      : ", KIND(R4)
      PRINT EFMT,  "HUGE      : ", HUGE(R4)
      PRINT EFMT,  "TINY      : ", TINY(R4)
      PRINT "(A G0)","TINY G0   : ", TINY(R4)
      PRINT IFMT,  "RANGE     : ", RANGE(R4)
      PRINT IFMT,  "PRECISION : ", PRECISION(R4)
      PRINT EFMT,  "EPSILON   : ", EPSILON(R4)

      PRINT "(A)",  "=== Real8 ==="
      WRITE (Lentest, '(G0)') HUGE(R8)
      WRITE (ExpLentest, '(G0)') RANGE(R8)
      WRITE (IFMT,1000) LEN_TRIM(Lentest)
      WRITE (EFMT,2000) LEN_TRIM(Lentest) - LEN_TRIM(ExpLentest) - 4

      PRINT IFMT,  "KIND      : ", KIND(R8)
      PRINT EFMT,  "HUGE      : ", HUGE(R8)
      PRINT EFMT,  "TINY      : ", TINY(R8)
      PRINT IFMT,  "RANGE     : ", RANGE(R8)
      PRINT IFMT,  "PRECISION : ", PRECISION(R8)
      PRINT EFMT,  "EPSILON   : ", EPSILON(R8)

      PRINT "(A)",  "=== Real16==="
      WRITE (Lentest, '(G0)') HUGE(R16)
      WRITE (ExpLentest, '(G0)') RANGE(R16)
      WRITE (IFMT,1000) LEN_TRIM(Lentest)
      WRITE (EFMT,2000) LEN_TRIM(Lentest) - LEN_TRIM(ExpLentest) - 4

      PRINT IFMT,  "KIND      : ", KIND(R16)
      PRINT EFMT,  "HUGE      : ", HUGE(R16)
      PRINT EFMT,  "TINY      : ", TINY(R16)
      PRINT IFMT,  "RANGE     : ", RANGE(R16)
      PRINT IFMT,  "PRECISION : ", PRECISION(R16)
      PRINT EFMT,  "EPSILON   : ", EPSILON(R16)

! IFMT '(A I0)'
1000  FORMAT ("(A I",I0,")")

! EFMT '(A G00.00)'
2000  FORMAT ("(A G0.",I0,")")

      END PROGRAM
tcsh
% gfortran MAX_Int.F90 && ./a.exe
=== Int ===
KIND     : 4
=== Int1 ===
KIND     :  1
HUGE     :127
RANGE    :  2
BIT_SIZE :  8
=== Int2 ===
KIND     :    2
HUGE     :32767
RANGE    :    4
BIT_SIZE :   16
=== Int4 ===
KIND     :         4
HUGE     :2147483647
RANGE    :         9
BIT_SIZE :        32
=== Int8 ===
KIND     :                  8
HUGE     :9223372036854775807
RANGE    :                 18
BIT_SIZE :                 64
=== Int16 ===
KIND     :                                     16
HUGE     :170141183460469231731687303715884105727
RANGE    :                                     38
BIT_SIZE :                                    128
=============
=== Real  ===
KIND      :              4
=== Real4 ===
KIND      :               4
HUGE      : 0.340282347E+39
TINY      : 0.117549435E-37
TINY G0   : 0.117549435E-37
RANGE     :              37
PRECISION :               6
EPSILON   : 0.119209290E-06
=== Real8 ===
KIND      :                        8
HUGE      : 0.17976931348623157E+309
TINY      : 0.22250738585072014E-307
RANGE     :                      307
PRECISION :                       15
EPSILON   : 0.22204460492503131E-015
=== Real16===
KIND      :                                           16
HUGE      : 0.118973149535723176508575932662800702E+4933
TINY      : 0.336210314311209350626267781732175260E-4931
RANGE     :                                         4931
PRECISION :                                           33
EPSILON   : 0.192592994438723585305597794258492732E-0033
%

それぞれの変数型で
KIND 変数を定義するときの KIND の値
HUGE 最大の値
TINY 最小の値
BIT_SIZE ビット数 (整数型のビット演算用)
RANGE 表現できる範囲が10進数で何桁か
PRECISION EPSILON の累乗部
EPSILON 1を代入した後、EPSILON より大きな値を足したときに差が出る (1 に対して切り捨てが起こらない最小値)

他にも DIGITS, MAXEXPONENT, MINEXPONENT, RADIX, NEAREST, RRSPACING ... 等、変数の精度に関する値を知るための関数が多数あるようです。

4
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?