質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

FORTRAN

FORTRAN(フォートラン)は科学時術計算に向いた手続き型プログラミング言語です。 並列計算の最適化が行いやすい特性上、数値予報および気候モデルなどの大規模な計算を行う分野のスーパーコンピュータで使われています。

Q&A

1回答

1477閲覧

ifの条件文にA or Bと書くとき、AとBが同値だとよくわからないことが起こる・・・

physics303

総合スコア89

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

FORTRAN

FORTRAN(フォートラン)は科学時術計算に向いた手続き型プログラミング言語です。 並列計算の最適化が行いやすい特性上、数値予報および気候モデルなどの大規模な計算を行う分野のスーパーコンピュータで使われています。

0グッド

0クリップ

投稿2016/11/01 12:25

Fortran初心者です。少々スクリプトがみにくいかもしれませんがお許しください。

関数chr(p,q)はp=qまたはpとqの差が±3であるときに1、それ以外で0をとる関数です。ただしp,qは整数とします。


chr(-1,-1)=1
chr(0,0)=1
chr(1,2)=0
chr(2,3)=0

-1≦p≦3,-1≦q≦3の範囲でpとqを変化させるプログラムをFortranで作ってみました。

Fortran

1program zheevtest 2 implicit none 3 4 interface 5 function chr(p,q) 6 implicit none 7 real :: chr 8 integer :: p,q 9 end function chr 10 11 end interface 12 13 14 write(*,*) chr(-1,-1) 15 write(*,*) chr(-1,0) 16 write(*,*) chr(-1,1) 17 write(*,*) chr(-1,2) 18 write(*,*) chr(-1,3) 19 write(*,*) 20 21 write(*,*) chr(0,-1) 22 write(*,*) chr(0,0) 23 write(*,*) chr(0,1) 24 write(*,*) chr(0,2) 25 write(*,*) chr(0,3) 26 write(*,*) 27 28 write(*,*) chr(1,-1) 29 write(*,*) chr(1,0) 30 write(*,*) chr(1,1) 31 write(*,*) chr(1,2) 32 write(*,*) chr(1,3) 33 write(*,*) 34 35 write(*,*) chr(2,-1) 36 write(*,*) chr(2,0) 37 write(*,*) chr(2,1) 38 write(*,*) chr(2,2) 39 write(*,*) chr(2,3) 40 write(*,*) 41 42 write(*,*) chr(3,-1) 43 write(*,*) chr(3,0) 44 write(*,*) chr(3,1) 45 write(*,*) chr(3,2) 46 write(*,*) chr(3,3) 47 write(*,*) 48 49 end program zheevtest 50 51 52function chr(p,q) 53 implicit none 54 integer :: chr 55 integer,intent(in) :: p,q 56 integer :: d 57 58 d=3 59 60 if(p==q .or. p==q-3 .or. p==q+3 .or. q==p+3 .or. q==p-3) then 61 chr=1 62 else 63 chr=0 64 end if 65 66return 67end function chr

すると、出力は次のようになります。


0.0000000E+00
0.0000000E+00
0.0000000E+00
1.000000
0.0000000E+00

0.0000000E+00
1.000000
0.0000000E+00
0.0000000E+00
1.000000

0.0000000E+00
0.0000000E+00
1.000000
0.0000000E+00
0.0000000E+00

1.000000
0.0000000E+00
0.0000000E+00
1.000000
0.0000000E+00

0.0000000E+00
1.000000
0.0000000E+00
0.0000000E+00
1.000000


ほとんどは意図した結果になっているのですが、納得がいかないところが1点あります。それはchr(-1,-1)が1ではなくて0であるとなっている点です。そこでこのソースコードをよく見なおしてみると、関数chr内のif条件文

Fortran

1p==q .or. p==q-3 .or. p==q+3 .or. q==p+3 .or. q==p-3

Fortran

1p==q .or. p==q-3 .or. p==q+3

と同値であるから、この部分を直してもう一度プログラムを実行すると、無事に


** 1.000000 **
0.0000000E+00
0.0000000E+00
1.000000
0.0000000E+00

0.0000000E+00
1.000000
0.0000000E+00
0.0000000E+00
1.000000

0.0000000E+00
0.0000000E+00
1.000000
0.0000000E+00
0.0000000E+00

1.000000
0.0000000E+00
0.0000000E+00
1.000000
0.0000000E+00

0.0000000E+00
1.000000
0.0000000E+00
0.0000000E+00
1.000000


とchr(-1,-1)が1であると出力されます。これはいったいどういうことなのでしょうか。

###質問
A1,A2,…,Anを命題とします。
A1またはA2またはA3または…Anというのは、「A1,A2,…,Anの1つ以上が真」であれば真であると思います。そのため、ifの条件文に同値な命題があっても実行される内容は同じだと思うのですが、上のようなことはなぜ起きてしまったのでしょうか・・・。またこういったことは他のプログラミング言語でも生じますか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ずっと昔にFortran77は学習したのですが、最近は全くやっていないので、
なにか不具合があるとは思うのですが、if文を次のように書かれてはいかがでしょうか?

ruby

1if (p - q).abs <= 3 2 puts 1 # 差の絶対値が3以下 (pとqが等しい場合ももちろん含む) 3else 4 puts 0 # 差の絶対値が3より大きい 5end

複雑なロジックのif文にするよりは、
シンプルなif文で良いかと思いますが、いかがでしょうか?

追伸:
出力結果をみて思い出しましたが、
原因は、浮動小数点数の誤差ではないでしょうか?
p, q の型が、integer であれば整数同士の演算ですので、誤差は生じませんが、
浮動小数点型であれば、.eq. など比較演算子は誤差を考慮して用いる必要があるかと思います。
詳しくは、誤差をご覧下さい。

投稿2016/11/01 16:08

編集2016/11/01 16:16
Atelier_Mirai

総合スコア68

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

physics303

2016/11/02 00:28 編集

コメントありがとうございます。 (p - q).abs <= 3 ならば chr(p,q)=1 は間違いです。 例えばchr(2,1)は引数の差の絶対値が3以下ですが、定義によりchr(2,1)=0です。おそらくAtelier_Miraiさんの意図するところは (p - q).abs == 3 .or. p==q ならば chr(p,q)=1 とすべしということですね。それならば納得です。 なお、このプログラム中に登場するpとqは整数なので誤差ではないと思ったのですが、よく見てみるとchrが実数で定義されていました。そこでchrを整数に定義しなおして、 if(p==q .or. p==q-3 .or. p==q+3) としてみても if(p==q .or. p==q+3 .or. p==q+3 .or. q==p+3 .or. q==p-3) としてみても意図したとおりの結果、つまりchr(-1,-1)=1となりました。 これで一応は解決したのですが、やっぱりなぜこうしたことが起こるのかはわかりません。 pとqが実数であれば、p==qの正誤判定が正しく(意図通りに)されない可能性があるのはわかりますが、chrが実数が整数かで結果がかわってくるのはなぜなのでしょう。
Atelier_Mirai

2016/11/02 10:24

解決したようで、何よりです。 差が3以内である時ではなく > 関数chr(p,q)はp=qまたはpとqの差が±3であるときに1 と書かれていましたね(^^ゞ 内部的に整数と浮動小数点数では、数値データの表現形式が異なります。 Wikipediaの誤差のページをご案内いたしましたが、もう読まれましたか? また、同じくWikipediaの浮動小数点数のページをご覧になると、理解が深まりますよ。
physics303

2016/11/03 00:00

桁落ちや整数と浮動小数点数についてはwikiは読みましたが、それでもやはり if(p==q .or. p==q+3 .or. p==q+3 .or. q==p+3 .or. q==p-3) と if(p==q .or. p==q+3 .or. p==q+3) で結果が異なることに納得がいきません。 これは本当に誤差の話なのでしょうか
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問