Fortran 入門

前へ   上へ   次へ

10 組込み手続

Fortran には、Fortran 言語にあらかじめ組込まれた関数やサブルーチンが用意されています。 これらは組込み手続と呼ばれ、Fortran 90 では約 100 種類が提供されています。 以下に良く利用されるものを示します。

組込み手続 意味
abs(x) 絶対値
acos(x) 逆余弦
asin(x) 逆正弦
atan(x) 逆正接
atan2(y,x) 逆正接(2つの値より)
sin(x) 正弦
cos(x) 余弦
tan(x) 正接
exp(x) 指数
log(x) 自然対数
int(a [,kind]) 整数へ変換(切り捨て)
nint(a [,kind]) 整数へ変換(四捨五入)
real(a [,kind]) 実数へ変換
dble(a) 倍精度実数への変換 real(a,kind(0d0)) と同じ
cmplx(x [,y] [,kind]) 複素数への変換
mod(a,p) a÷p の余り
sqrt(x) 平方根
max(a1,a2[,a3,...]) 最大値
min(a1,a2[,a3,...]) 最小値
len(a) 文字長
len_trim(a) 後ろの空白を除いた文字長
achar(i) i によって示される ASCII 文字
iachar(a) a によって示される ASCII 文字のコード
bit_size(i) i のビット数
btest(i,pos) i の pos+1 番目のビットが 1 かどうか
iand(i,j) i と j のビットごとの論理積
ior(i,j) i と j のビットごとの論理和
ieor(i,j) i と j のビットごとの排他的論理和
ibclr(i,pos) i の pos+1 番目のビットを 0 に設定
ibset(i,pos) i の pos+1 番目のビットを 1 に設定
not(i) i の論理否定

以下に組込み関数の利用例を示します。

[ intrinsics.f90 ] - 組込み関数を用いるサンプル

program intrinsic_sample
  implicit none
  integer :: i = 99
  real :: a = 2.5
  print *, "i=", i
  print *, "a=", a
  print *, "real(i)=", real(i)
  print *, "dble(i)=", dble(i)
  print *, "int(a)=", int(a)
  print *, "nint(a)=", nint(a)
  print *, "sin(0.5)=", sin(0.5)
  print *, "sin(0.5d0)=", sin(0.5d0)
  print *, "sqrt(10.0)=", sqrt(10.0)
  print *, "mod(10,3)=", mod(10,3)
  do i=iachar("A"), iachar("A")+4
    print *, achar(i)
  end do
end program intrinsic_sample

出力例:
 i= 99
 a=   2.5000000
 real(i)=  99.0000000
 dble(i)=  99.0000000000000000
 int(a)= 2
 nint(a)= 3
 sin(0.5)=   0.4794255
 sin(0.5d0)=   0.4794255386042030
 sqrt(10.0)=   3.1622777
 mod(10,3)= 1
 A
 B
 C
 D
 E

10.1 総称名と個別名について

組込み手続を呼び出した場合に与える引数の型により内部的に別の関数が呼び出される場合があります。 例えば、

a = sqrt(b)

と記述した場合に、b の型が倍精度実数であれば内部的に倍精度実数版の関数により計算が行われます。 またもし b の型が倍精度複素数であれば内部的に倍精度複素数版の関数により計算が行われます。

例:
program generic_vs_specific
  implicit none
  double precision :: a = 2.0
  complex(kind(0d0)) :: b = (2.0,1.0)
  print *, sqrt(a)
  print *, sqrt(b)
end program generic_vs_specific

実行例:
   1.4142135623730951
 (1.4553466902253549,0.3435607497225124)

内部的に呼び出される関数は Fortran 標準で規定されているものとそうではないものが存在します。 例えば上記例において sqrt(倍精度実数) は内部的に dsqrt という関数を呼び出します。 dsqrt 関数は Fortran 標準でも規定されている関数で倍精度実数型の引数を取り倍精度実数型を返す関数です。 一方で sqrt(倍精度複素数) は内部的にまた別の関数を呼び出しますが、呼び出される関数の名前は Fortran 標準では規定されていません。

ここで sqrt(任意の実数型もしくは複素数型) は総称名と呼ばれ、dsqrt(倍精度実数) は個別名と呼ばれます。 総称名を利用することにより引数の型に基づき適切な内部関数が呼び出されることになります。 また総称名の代わりに個別名を利用するメリットはほぼ皆無に等しいこともあり、組込み手続の利用は総称名で行うことが強く推奨されています。

組込み関数の個別名には上記 dsqrt のように Fortran 標準で規定されているものの他に、様々なコンパイラメーカーが独自に拡張した非標準のものが存在します。 例えばあるコンパイラメーカーでは倍精度複素数の sqrt を zsqrt と呼び、また別のコンパイラメーカーでは cdsqrt 等と呼んでいます。 このような非標準の組込み関数はプログラムのポータビリティーを損ないますので利用せずに、その代りに総称名を利用することが強く推奨されています。

以下に Fortran 標準に含まれる個別名一覧及び対応する総称名を示します。

説明 総称名形式 個別名 引数型 関数型
整数への変換 int(a) int 単精度実数 整数
ifix 単精度実数 整数
idint 倍精度実数 整数
実数への変換 real(a) real 整数 単精度実数
float 整数 単精度実数
sngl 倍精度実数 単精度実数
最大値 max(a1,a2,…) max0 整数 整数
amax1 単精度実数 単精度実数
dmax1 倍精度実数 倍精度実数
amax0 整数 単精度実数
max1 単精度実数 整数
最小値 min(a1,a2,…) min0 整数 整数
amin1 単精度実数 単精度実数
dmin1 倍精度実数 倍精度実数
amin0 整数 単精度実数
min1 単精度実数 整数
s1 >= s2 lge(s1,s2) lge 文字 論理
s1 > s2 lgt(s1,s2) lgt 文字 論理
s1 <= s2 lle(s1,s2) lle 文字 論理
s1 < s2 llt(s1,s2) llt 文字 論理
a の絶対値 * b の符号 sign(a,b) isign 整数 整数
sign 単精度実数 単精度実数
dsign 倍精度実数 倍精度実数
x-y と 0 の大きい方の値 dim(x,y) idim 整数 整数
dim 単精度実数 単精度実数
ddim 倍精度実数 倍精度実数
x*y dprod(x,y) 単精度実数 倍精度実数
小数点以下切り捨て aint(a) aint 単精度実数 単精度実数
dint 倍精度実数 倍精度実数
最近傍整数 anint(a) anint 単精度実数 単精度実数
dnint 倍精度実数 倍精度実数
最近傍整数への変換 nint(a) nint 単精度実数 整数
idnint 倍精度実数 整数
絶対値 abs(a) iabs 整数 整数
abs 単精度実数 単精度実数
dabs 倍精度実数 倍精度実数
cabs 単精度複素数 単精度実数
余り mod(a,p) mod 整数 整数
amod 単精度実数 単精度実数
dmod 倍精度実数 倍精度実数
平方根 sqrt(x) sqrt 単精度実数 単精度実数
dsqrt 倍精度実数 倍精度実数
csqrt 単精度複素数 単精度複素数
指数 exp(x) exp 単精度実数 単精度実数
dexp 倍精度実数 倍精度実数
cexp 単精度複素数 単精度複素数
自然対数 log(x) alog 単精度実数 単精度実数
dlog 倍精度実数 倍精度実数
clog 単精度複素数 単精度複素数
常用対数 log10(x) alog10 単精度実数 単精度実数
dlog10 倍精度実数 倍精度実数
正弦 sin(x) sin 単精度実数 単精度実数
dsin 倍精度実数 倍精度実数
csin 単精度複素数 単精度複素数
余弦 cos(x) cos 単精度実数 単精度実数
dcos 倍精度実数 倍精度実数
ccos 単精度複素数 単精度複素数
正接 tan(x) tan 単精度実数 単精度実数
dtan 倍精度実数 倍精度実数
逆正弦 asin(x) asin 単精度実数 単精度実数
dasin 倍精度実数 倍精度実数
逆余弦 acos(x) acos 単精度実数 単精度実数
dacos 倍精度実数 倍精度実数
逆正接 atan(x) atan 単精度実数 単精度実数
datan 倍精度実数 倍精度実数
逆正接(y/x) atan2(y,x) atan2 単精度実数 単精度実数
datan2 倍精度実数 倍精度実数
双曲線正弦 sinh(x) sinh 単精度実数 単精度実数
dsinh 倍精度実数 倍精度実数
双曲線余弦 cosh(x) cosh 単精度実数 単精度実数
dcosh 倍精度実数 倍精度実数
双曲線正接 tanh(x) tanh 単精度実数 単精度実数
dtanh 倍精度実数 倍精度実数
虚数部 aimag(z) aimag 単精度複素数 単精度実数
複素共役 conjg(z) conjg 単精度複素数 単精度複素数
文字長 len(s) len 文字 整数
開始位置 index(s,t) index 文字 整数

補足:
上記一覧にはコンパイラメーカーの独自の拡張である Fortran 言語非標準の個別名は含まれていません。 これらの非標準な個別名をリストアップすることは不可能ですが、一般的なルールとして例えば "xFUN" のような非標準個別名の代わりに総称名 "FUN" を使用してください。 (ここで "x" は1文字または複数文字の個別名の接頭辞、"FUN" は数学関数の名前です。)

(良く利用される)数学関数の名前:
ABS, ACOS, ASIN, ATAN, ATAN2, CONJG, COS, COSH, DIM, EXP, LOG, LOG10, MAX, MIN, SIGN, SIN, SINH, SQRT, TAN, TANH

(典型的な)個別名の接頭辞:
C, CD, CQ, D, DC, Q, Z

例えば、非標準個別名 CDEXP, DCEXP, QEXP, CQEXP, ZEXP はどれも総称名 EXP に置き換えて同じ結果を得ることができます。

10.2 余りを求める組込み関数について

割り算の余りを求めるためには mod() 組込み関数を用いることができます。
  print *, mod(10, 3)  ! 10÷3 の余りを表示
出力例:
 1

10.3 ビット操作を行う組込み関数

ビット操作を行う組込み関数も用意されています。 以下にサンプルを示します。

[ bit-operations.f90 ] - ビット操作を行うサンプル
program bit_operations
  implicit none
  integer :: i = 0
  call print_bits(i,"i=0")
  i = ibset(i,4)    ! 5 番目のビットを設定
  call print_bits(i,"ibset(i,4)")
  i = not(i)        ! すべてのビットを反転
  call print_bits(i,"i=not(i)")
  i = ibclr(i,2)    ! 3 番目のビットをクリア
  call print_bits(i,"i=ibclr(i,2)")
  i = ishft(i,5)   ! 5
ビット右へシフト
  call print_bits(i,"i=ishft(i,5)")
  i = ieor(i,i)    ! 同じ値どうしの排他的論理和
  call print_bits(i,"i=ieor(i,i)")
contains
  subroutine print_bits( num, msg )
    integer num, i
    character(*) msg
    character(bit_size(num)) a
    a = "";
    do i=1, bit_size(num)
      if ( btest(num,i-1) ) then
        a = trim(a) // "1"
      else
        a = trim(a) // "0"
      end if
    end do
    print *, a, " : ", msg
  end subroutine print_bits
end

出力例:
 00000000000000000000000000000000 : i=0
 00001000000000000000000000000000 : ibset(i,4)
 11110111111111111111111111111111 : i=not(i)
 11010111111111111111111111111111 : i=ibclr(i,2)
 00000110101111111111111111111111 : i=ishft(i,5)
 00000000000000000000000000000000 : i=ieor(i,i)

10.4 ★ 練習課題:素数を求める

入力した値以下の素数をすべて出力するプログラムを作成して下さい。

処理手順例

  1. 変数を宣言する
     例)
     integer i, j, n
     logical sosu_desu
  2. N を入力してほしい旨を画面に出力する(print 文)
  3. N をキーボードから入力する(read 文)
  4. 2 から n までについて調べるために反復(do)文を記述する
     例)
     do i=2,n
  5. 素数であるかどうかのフラグを真に設定しておく
     例)
     sosu_desu = .true.
  6. 2 から i-1 までについて(int(sqrt(dble(i))) まで調べるだけでも良い)、割り切れるかどうか調べるために反復する
     例)
     do j=2,i-1
  7. 割り切れるかどうかによりフラグを設定する
     例)
     if ( mod(i,j) == 0 ) sosu_desu = .false. ! 割り切れるので素数ではない
  8. 内側のループ終了後に sosu_desu フラグが真であれば i を出力する
  9. 外側のループ終了
実行例:
 Please enter N:
29
 2
 3
 5
 7
 11
 13
 17
 19
 23
 29
[ kadai-sosu.f90 ] - 素数を求めるプログラム例


前へ   上へ   次へ
大学生協限定キャンペーン情報
ご案内
関連情報
© 日本ニューメリカルアルゴリズムズグループ株式会社 2025
Privacy Policy  /  Trademarks