大学でFortran95を使うことがあったので、教材で配布されている問題を解いてみた。
環境はMacのVSCodeでModern Fortranを使って行った。
------memo------は初心者の方に役立つかもしれない情報を載せた
まだ授業が終わってなく提出コードが酷似するのを防ぐため
きちんと動くが不細工なコードになるように変更した
変数名abcは各自で変更しろという箇所
問題 (2.2.1) 2 つの実数を読み込み、加減乗除を出力する。
program abc
implicit none
real abc1,abc2,abc
print *, "abc1を入力してください"
read(*,*) abc1
print *, "abc2を入力してください"
read(*,*) abc2
abc = abc1 + abc2
print *, "abc1 + abc2 = ", abc
stop
end program abc
------memo------
printとwriteはほとんど同じ しかし、writeはファイルの書き込みが可能なのでwriteで統一するべきかも
readは入力された値を変数に代入する
realは実数 integerは整数
numとはnumberの略、数値を代入する際よく使われる
問題 (2.2.2) 実数 a と b を読み込んで、a と b の算術平均(i.e., 足して2で割る)と幾何平均(i.e., 積のルート)を計算するプログラムを作成せよ。
大学の教授たちは何故わかりにくい言葉を使いたがるのか謎だが、
この問題をわかりやすくすると、
step1. 実数a,bを読み込む
step2. a,bの平均を求めよ
step3. a,bの積のルートを求めよ
program abc
implicit none
real abc1,abc2,abc3,abc4
print *, "abc1を入力してください"
read(*,*) abc1
print *, "abc2を入力してください"
read(*,*) abc2
abc3 = (abc1 + abc2) / 2
abc4 = (abc1 * abc2) ** 0.5
print *, "平均値", abc3
print *, "積のルート", abc4
stop
end program abc
------memo------
sum()などあると思ったが、なさそう(自分で関数を作るのか?)なので普通に作った。
追記 配列に入れsumする方法があった
問題 (2.2.3) x を入力し、1/(2+2x+x^2) を出力する。
program hello
real abc,abc2,abc3,abc4
print *, "abcを入力してください"
read(*,*) abc
abc2 = 2 * abc
abc3 = abc ** 2
abc4 = 1/(2+abc2+abc3)
print *, "1/(2+2abc+abc^2) = ", abc4
stop
end program hello
------memo------
割り算がある為、実数のrealを使用
わかりやすいようにtwoTimeとsquareに分けた
問題 (2.2.4) x 時 y 分 z 秒から k 時 m 分 n 秒まで何秒あるかを計算する。
発展問題
program hello
implicit none
integer hour1,hour2,min1,min2,sec1,sec2
print *, "時、分、秒を順番に入力してください"
read(*,*) hour1,min1,sec1
print *, "差分を求めたい 時、分、秒を順番に入力してください"
read(*,*) hour2,min2,sec2
sec1 = (hour1 * 3600) + (min1 * 60) + sec1 !時間,分を全て秒に変換
sec2 = (hour2 * 3600) + (min2 * 60) + sec2
sec1 = abs(sec1 - sec2) !絶対値
hour1 = int(sec1 / 3600) !秒から時間へ
sec1 = modulo(sec1,3600) !時間を引いた秒
min1 = int(sec1 / 60)
sec1 = modulo(sec1,60)
print *, "差分は",hour1,"時間",min1,"分",sec1,"秒"
stop
end program hello
------memo------
時間、分を秒数に変換するという発想がミソ
入力形式を hh : mm : ss にしたかったが、めんどくさそうだったのでやめた
問題 (2.3.1) 2 次方程式 ax^2 + bx + c = 0 の係数 a,b,c を読み込んで、その根を表示する。
program hello
implicit none
real a,b,c,ansPlus,ansMinus,d
print *, "a,b,cの値を順番に入力してください"
read(*,*) a,b,c
if (a == 0) then
ansPlus = c / b
print *, "x = ",ansPlus
else
d = b**2 - 4*a*c
if (d >= 0) then
ansPlus = (-b + sqrt(d)) / 2*a
ansMinus = (-b - sqrt(d)) / 2*a
print *, "x = ",ansPlus,",",ansMinus
else
print *, "虚数解です"
end if
end if
stop
end program hello
------memo------
解の公式を使用する
a = 0 の時の条件文を追加
問題 (3.1) 整数 n から整数 m までの和を計算する。
program hello
implicit none
integer total,n,m,i
print *, "整数n,整数mを順番に入力してください"
read (*,*) n,m
if (n > m) then
total = m
m = n
m = total
end if
total = 0
do i = n, m
total = total + i
end do
print *, "和は",total
stop
end program hello
------memo------
for文で n > mの時の対応
ループ文で nからmまでm-n+1回ループする
問題 (3.2) 関数 y = x^2の x = x1 から x = x2 までの範囲で、積分を計算する。xy 平面の y = x^2のグラフの下の部分の面積を、x について微小区間(幅がΔx)の矩形の和として求めよ。x1x2 、およびΔx は標準入力から読み込む。
難しい言葉が出てきて頭痛い
整理すると
step.1 x1,x2,Δx を読み込む
step.2 x1からx2までの範囲でy = x^2 を積分するが,
step.3 積分する際の長方形の面積幅を使用する形で積分せよ
ということなのか??
積分とは長方形の面積の和である
例えば3から5までの区間をΔx = 1で という問題だったら
x = 3の時y = x^2 より y = 9 長方形の面積は 91
x = 4の時y = x^2 より y = 16 長方形の面積は 161
よって面積の和は25
長方形よりも台形にした方が誤差は小さくなるのでは?と思うが。。。
矩形(クケイ)-> 連続する自然数の積 長方形数、長方数 とも呼ばれる
program hello
implicit none
real x1,x2,delX,ans
print *, "x1,x2,Δxを順番に入力してください"
read (*,*) x1,x2,delX
ans = 0
if (x1 < x2) then !x2がx1より大きくないか確認
if (x2 - x1 > delX ) then !Δxが大きすぎないか確認
do while (x1 /= x2) !x1 == x2になるまでループ
if (x1 > x2) then
delX = x2 - (x1 - delX) !x1がx2より大きくなった場合残りの面積を求める
end if
ans = ans + ((x1 ** 2) * delX) !長方形の面積を足していく
x1 = x1 + delX !長方形の座標を変える
end do
else
print *, "ERROR [内容:Δxの値が大きすぎます]"
end if
else
print *, "ERROR [内容:x2よりx1が大きいです]"
end if
print *, "面積は",ans
stop
end program hello
------memo------
とりあえず解けたが問題文の解釈間違いで間違っている気がする。。。
アルゴリズムの考え方というより数学的な考え方
問題 (4.1) 問題 (2.3.1) での2次方程式を解く問題で、解が虚根になるときは、そのことを述べて終わるように改良する。
問題 4.2 自然対数の底 e を、精度 10^-5 で求めよ。ここで、写真.1を利用せよ。
program hello
implicit none
real num,count,accuracy,ans_e
num = 1 ! 階乗の計算
count = 0 !分母の数字
accuracy = 10 ** 5 !精度
ans_e = 1 !eの計算
do while (num <= accuracy ) ! 分母だけ考える
count = count + 1 ! 分母の数字を1増やす
num = num * count ! 分母の階乗の値を求める
ans_e = ans_e + (1/num) ! 計算
end do
print *, "自然対数eの値は e = " , ans_e , "[精度は10^-5]"
stop
end program hello
気分が向いたら更新予定