この文書の URL は http://www.cc.kyoto-su.ac.jp/~mtkg/lecture/comp_B/2012/02.html です。

四則演算

次のプログラムを作成し加減乗除を試してみましょう。 割り算(商を求める演算子)は / です。

!
! 加減乗除
!
program work0201
  implicit none
  integer :: nx, ny

  write(*,*) 'Inputs two integers:'
  read(*,*) nx, ny

  write(*,*) 'nx + ny = ', nx + ny
  write(*,*) 'nx - ny = ', nx - ny
  write(*,*) 'nx * ny = ', nx * ny
  write(*,*) 'nx / ny = ', nx / ny

  stop
end program work0201

プログラムを実行すると入力待ちの状態になります。 24 と 5 を空白で区切って入力しリターンキーを押すと、read 文の入力並びに書いた順番にしたがって nx に 24, ny に 5 がセットされます。

% ./a.out
 Inputs two integers:
24 5
 nx + ny =           29
 nx - ny =           19
 nx * ny =          120
 nx / ny =            4

整数の割り算

割り算の結果に注意してください。

整数 / 整数

という計算では「商の整数部」(小数点以下を切り捨てた値)が得られます。 このため 24 / 5 は 4.8 にならず 4 になります。

平均値の計算

2つの整数値を読み込んで平均値を表示するプログラムを作成してみましょう。 ファイル名は work0202.f90 とします。

program work0202
  implicit none
  integer :: nx, ny

  write(*,*) 'Inputs two integers:'
  read(*,*) nx, ny

  write(*,*) 'mean = ', (nx + ny) / 2

  stop
end program work0202

計算の優先順序

nx + ny( ) で囲んで正しい順序で計算されるようにします。 Fortran では通常の演算規則と同じように演算の優先順序が決められています。

結果の型

いくつか試してみましょう。

% ./a.out
 Inputs two integers:
10 12
 mean =           11
% ./a.out
 Inputs two integers:
10 13
 mean =           11

10 と 12 の平均は正しく計算できていますが、10 と 13 の結果は変ですね。 Fortran では「整数 / 整数」の結果が整数になり、結果の小数部分が切り捨てられるので、このような結果になります。 平均を正しく計算するには次の「実数型」を使います。

実数型

Fortran では実数を浮動小数点数 (floating point number) という形式で表します。 実数型にはいくつかの種類がありますが、一般的には real(8) 型が使われます。

real(8) 型は次の範囲の実数を「近似的に」表すことができます。

ここで 10^n は 10 の n 乗を表すものとします。

整数型と実数型の性質の違いをみるために、次のようなプログラムを作成してみましょう。

program work0203
  implicit none
  integer :: nx                          ! 整数型
  real(8) :: dx                          ! 実数型

  nx = 9.99                              ! 整数型に実数を代入
  dx = 9.99                              ! 実数型に実数を代入

  write(*,*) 'nx     = ', nx
  write(*,*) 'dx     = ', dx
  write(*,*) 'nx / 2 = ', nx / 2
  write(*,*) 'dx / 2 = ', dx / 2

  stop
end program work0203

これを実行すると次のようになります。

% ./a.out
 nx     =            9
 dx     =    9.9899997711181641
 nx / 2 =            4
 dx / 2 =    4.9949998855590820

この結果から次のことがわかります。

型と演算

Fortran では、演算を構成している定数や変数の型がすべて同じ場合は、結果も同じ型になります。 例えば、「整数 / 整数」の結果は整数型、「実数 / 実数」の結果は実数型になります。

一方、「実数 / 整数」や「整数 / 実数」のように演算の対象が異なる型の場合は、整数型が実数型に変換されてから演算が行われます。 例えば、「5.0 / 2」という演算では 2 が 2.0 という実数型の数値に変換されてから計算されます。

こうした規則は割り算 / だけでなく +-, * にも同様に適用されます。

定数の型

real(8) 型の定数は「10 を基数とする指数表現」を使って次のように表すことができます。

実数定数     意味
-----------------------------------------------------------------
3.14d+0      3.14 x 10^0    --> 3.14
1.25d+3      1.25 x 10^3    --> 1250.0
0.8d-3       0.8  x 10^(-3) --> 0.0008

指数表現を使わずに「型パラメータ」を指定して表すこともできます。

12.0_8       12.0d+0 と同じ
-0.2_8       -0.2d+0 と同じ

数字_8 の 8 は real(8) の 8 に対応しています。 この数字のことを型パラメータといいます。

注意

単に 3.14 などと書くと real(4) 型という精度の低い別の実数型になってしまうので注意しましょう。 real(4) 型は精度が10進数で約6桁(2進数で24桁)しかありません。

平均値の計算 (2)

2つの整数値を読み込んで平均値を「正しく」計算するプログラムを作成してみましょう。 ファイル名は work0204.f90 とします。

program work0204
  implicit none
  integer :: nx, ny

  write(*,*) 'Inputs two integers:'
  read(*,*) nx, ny

  write(*,*) 'mean = ', (nx + ny) / 2.0d+0

  stop
end program work0204

実際に行われる計算

平均を求める式 (nx + ny) / 2.0d+0 に注目してみましょう。 work0202.f90 との違いは 22.0d+0 になっただけです。 計算機の中で行われる計算は次のようになります。

Fortran プログラミングでは常に「型」を意識することが大切です。

型変換の組込み関数

組込み関数 dble(整数型)real(整数型, kind=8) を使うと、整数型の定数や変数を実数型 (real(8) 型)に変換することができます。

したがって、平均を求める式は次のように書くこともできます。

dble(nx + ny) / 2
real(nx + ny, kind=8) / 2

この場合は nx + ny の結果(整数型)が実数型に変換され、「実数型 / 2」の計算が行われます。 整数型の定数 2 は自動的に実数型に変換され、演算の結果は実数型になります。

Fortran には実数型を整数型に変換する組込み関数も用意されています。

int(x)      小数部分を切り捨てて整数化する。
nint(x)     実数 x にもっとも近い整数を返す。

符号の反転

値の符号を反転させるには - 演算子を使います。

program work0205
  implicit none
  integer :: nx

  write(*,*) 'Inputs an integer:'
  read(*,*) nx

  write(*,*) '-nx = ', -nx

  stop
end program work0205

符号を変化させない + 演算子もありますが、ほとんど使われません。

剰余

2つの整数値を読み込んで、その商と剰余(割り算の余り)を表示してみましょう。 整数 a を整数 b で割った余りを計算するには、

a - (a を b で割った商の整数部分) * b

を計算すればよいですね。 a, b が整数型なので a / b が「a を b で割った商の整数部分」になります。

program work0206
  implicit none
  integer :: nx, ny

  write(*,*) 'Inputs two integers:'
  read(*,*) nx, ny

  write(*,*) 'div = ', nx / ny
  write(*,*) 'mod = ', nx - (nx / ny) * ny

  stop
end program work0206

正しく計算できるか確かめてみましょう。

% ./a.out
 Inputs two integers:
27 6
 div =            4
 mod =            3

練習問題

剰余は mod という組込み関数(あらかじめ用意されている関数のこと)を使って計算することもできます。 mod(a, b) で整数 a を整数 b で割った余りが計算されます。 上の例に

write(*,*) 'mod = ', mod(nx, ny)

を加えて試してみましょう。

本日の課題

1. 組込み関数 int

組込み関数 int を利用して、キーボードから読み込んだ実数の小数部分を求めるプログラムを作成せよ。 ある実数の小数部分を求めるには整数部分を引けばよい。

program work0207
  implicit none
  real(8) :: dx

  write(*,*) 'Input a real:'
  read(*,*) dx

  write(*,*) dx - int(dx)

  stop
end program work0207

2. 相加平均と相乗平均

2つの実数を読み込んで、相加平均と相乗平均を計算するプログラムを作成せよ。 相乗平均の計算には平方根を計算する sqrt(実数型) という組込み関数を利用する。

program work0208
  implicit none
  real(8) :: dx, dy

  write(*,*) 'Input two reals:'
  read(*,*) dx, dy

  write(*,*) 'souka = ', (dx + dy) / 2
  write(*,*) 'soujo = ', sqrt(dx * dy)

  stop
end program work0208

3. いろいろな平均

3つの実数を読み込んで算術平均、幾何平均、調和平均を計算するプログラムを作成せよ。 3つの数 X, Y, Z の算術平均 A, 幾何平均 G, 調和平均 H は次のように定義される。

A = (X + Y + Z) / 3
G = (X * Y * Z)**(1/3)
1/H = (1/X + 1/Y + 1/Z) / 3

立方根の計算にはべき乗の演算子 ** を利用する。 x**y は x の y 乗を表す。 したがって、実数型の変数 dx, dy, dz の積の立方根 (1/3 乗) を計算するには

(dx * dy * dz)**(1.0d+0 / 3)

とすればよい。 (dx * dy * dz)**(1 / 3) では (dx * dy * dz)**0 になってしまうので注意すること。

!
! いろいろな平均
!
program work0209
  implicit none
  real(8) :: x, y, z
  real(8) :: a, g, h

  write(*,*) 'Input three potitive reals:'
  read(*,*) x, y, z

  a = (x + y + z) / 3
  g = (x * y * z)**(1.0d+0 / 3)
  h = (1/x + 1/y + 1/z) / 3              ! h には 1/H が入る
  h = 1 / h                              ! 1/H => H

  write(*,*) a, g, h

  stop
end program work0209