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

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

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

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

FORTRAN

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

Q&A

解決済

2回答

5312閲覧

fortran & C:計算結果が毎回異なる

wanwannyaan

総合スコア31

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

FORTRAN

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

0グッド

0クリップ

投稿2019/07/08 08:44

編集2019/07/08 10:30

fortranでcos(x)をYからXの範囲で台形積分するプログラムをC言語のプログラムから呼び出すコードを書いています。
今回の質問はそのfortranの部分についてで、毎回異なった計算結果が表示されるのですが、fortran初心者すぎて何が理由かわかりません。以下がそのfortranのコードです。また、このコードを呼び出すCプログラムを一番下に置いておきます。

入力はプログラムの実行時にコマンドライン引数で任意の2数を指定して、出力は入力した2数の範囲でcos(x)を台形積分した結果として正しい値が帰ってくることを期待しています。
実際に実行したところ、実行する度に違う結果が出ました。(以下は入出力例です。)

input

1./JikkouFile_Name 1.5707963 0

output

1b=1.570796 2a=0.000000 3 1.5707963000000000 0.0000000000000000 4.59149455E-41 4 -469083744 -469083744.00000000 5-469083744.000000

fortran

1 DOUBLE PRECISION FUNCTION SEKIBUN(X,Y) 2 DOUBLE PRECISION X 3 DOUBLE PRECISION Y 4 INTEGER I 5 DOUBLE PRECISION WIDTH=(X-Y)/10000000 6 DOUBLE PRECISION MENSEKI=0.0 7 PRINT *,X,Y,WIDTH 8 DO I=0,10000000 9 MENSEKI=MENSEKI+DCOS(I*WIDTH+Y)*WIDTH 10 END DO 11 SEKIBUN=MENSEKI 12 PRINT *,MENSEKI,SEKIBUN 13 RETURN 14 END

C

1#include <stdio.h> 2#include <stdlib.h> 3 4extern double sekibun_(double *, double *); 5 6int main(int argc, char **argv){ 7 double a,b,menseki; 8 b = atof(argv[1]); 9 a = atof(argv[2]); 10 printf("b=%lf\na=%lf\n",b,a); //(*1*) 11 menseki = sekibun_(&b, &a); 12 printf("%lf\n",menseki); //(*2*) 13 return 0; 14}

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

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

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

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

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

otn

2019/07/08 10:06

「こういう入力に対して、こういう結果を期待したが、こう出力された」という風に書いてください。
izmktr

2019/07/08 10:16

一度、FORTRAN側の処理を渡した引数を表示するだけとか、 FORTRAN側が固定値を返してCで表示するだけとか、そういう処理で確認してみるのはどうでしょうか 毎回変わるなら、Cがポインタで引数を渡しているのが原因なんじゃないかと思いますが…
wanwannyaan

2019/07/08 10:27

FORTRANの出力系を調べてもよくわからなくて、やっていなかったのですが、再度調べ直したところ理解できたのでやってみました。 やってみた結果、C→fortran, fortran→Cのデータの受け渡しで数値が変わっていることはなかったので、fortran側に間違いがあるようです。 とりあえず、これから質問内容に反映します。
guest

回答2

0

ベストアンサー

MENSEKI が save 変数になっているので、前回の値が残っていて、どんどん加算されてゆく。

fortran

1DOUBLE PRECISION MENSEKI=0.0

短冊形の積分をするのに 10000000 分割するのも理解しがたい。しかも端点の処理がされていないので、いくら細かく分割したところで期待している値には収束しないだろう。中点積分の方がまし。

もっと少ない分割数で、分割数を変えて計算して、収束の度合いを見る方がはるかに有益だろう。あと2進法コンピュータなら 2 のべき乗で分割しておいた方が色々都合がいいことが多い。

fortran

1integer, parameter :: n = 128

初心者ということで、仕方ないとは思うが FORTRAN77 以前の古い規格の書き方をしつつ、五月雨式に Fortran90 以降の機能を使っているので分かり難い。

まず implicit none はつけたほうがいい。

77 までの正規の名称ではあるが、DOUBLE PRECISION を使うのは避ける方がどちらかといえば賢明。倍精度だからと言って DCOS を使うのもよくない。77 以降では総称名の COS の方が一般的。

FORTRAN77 以前を主たる書き方にするならは、暗黙の型を守るのは絶対なので MENSEKI という変数名もよくない。鼻の穴から牛乳飲むレベルの異常感。

C 言語から呼ぶなら Fortran 2003 以降の機能になるが、bind 属性をつければ、そこで指定した名前で C 側から見える。アンダースコアなどは、ベンダー毎に代わっている。

fortran

1DOUBLE PRECISION FUNCTION SEKIBUN(X,Y) bind(c, name = 'sekibun')

投稿2019/07/08 12:58

curehoney

総合スコア249

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

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

0

WIDTHの表示値がおかしいですね。
変数宣言と、代入を分けてみては?

投稿2019/07/08 10:57

otn

総合スコア84538

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

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

wanwannyaan

2019/07/08 11:32

WIDTHの部分、 DOUBLE PRECISION WIDTH WIDTH=(X-Y)/10000000 のように修正したところ、出力が次のようになり、WIDTHの値は正しく計算されているようです。また、積分値は直りませんでしたが(出力1.000000を期待している)、何度やっても同じ結果が表示されるようにはなりました。ありがとうございます。 b=1.570796 a=0.000000 1.5707963000000000 0.0000000000000000 1.5707963000000001E-007 32766 32766.000000000000 32766.000000
otn

2019/07/08 11:39

規格を確認していませんが、宣言文の式右辺の評価は、呼び出し前に行われるのでは?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問