くだすれFORTRAN(超初心者用)その6
■ このスレッドは過去ログ倉庫に格納されています
このスレッドは、他のスレッドでは書き込めない超低レベル、 もしくは質問者自身何が何だか分からない質問を勇気を持って書き込むスレッドです。 FORTRAN使いが優しくコメントを返しますが、 お礼はFORTRANの布教と初心者の救済と次期Fortran2008規格でのCOMEFROM文採用をお願いします。 ●注意事項 ・質問する前にGoogle等の検索サイトで検索しましょう。 ・回答者にわかりやすい様に、質問内容はできる限り詳しく書きましょう。 ・エラーの場合は起きた状況、環境(OS・コンパイラ・バージョン)、エラーメッセージも詳しく書きましょう。 ●前スレ くだすれFORTRAN(超初心者用)その5 http://toro.2ch.net/test/read.cgi/tech/1269704830/ ●過去スレ くだすれFORTRAN(超初心者用)その4 http://pc12.2ch.net/test/read.cgi/tech/1232789521/ くだすれFORTRAN(超初心者用)その3 http://pc11.2ch.net/test/read.cgi/tech/1196384126/ くだすれFORTRAN(超初心者用)その2 http://pc11.2ch.net/test/read.cgi/tech/1164121236/ くだすれFORTRAN(超初心者用) http://pc8.2ch.net/test/read.cgi/tech/1138063703/ intelは自動並列化があるから中級者は使用を薦める このレス数からしてFortran使ってる人はほとんどいないのかな? ここでの質問は学生がほとんどのように見える 一般人は使わないだろうから少ないのは確かだろうけど 調べたり相談できる人が多いんじゃない? >>788 なるほど じゃあ私遠慮無く質問しまくっちゃっおうかな fortran の組み込み関数でminval ってのがありますよね. ある配列a(要素は一つだけ)に関して minval(a,dim=1,mask=a>0.0d0)すると値が1e-324みたく値がおかしくなるんですが原因として考えられるものは何でしょう? ちなみに配列aの中身は a(1)= 4.2e-2です。 なので期待する値は minval(a,dim=1,mask=a>0.0d0)=4.2e-2になるはずなんですが。。。 >>790 なんとなく初期化してない変数が引っかかっている気がする minvalの動作不良を疑うならコンパイラとか環境を書こう 違うならソースをできるだけ書こう 長くてソース貼れないならこんな感じに晒すと検証が楽 https://ideone.com/JstGnQ >>790 単精度を入れているのに倍精度で値が返ってきているのが気になる。 なんか倍精度と単精度をまぜこぜにしているか、コンパイラが間違っていてまぜこぜにしている。 g95はデフォの変数長を変えたせいで混乱に陥った。その辺かな? FortranはRealとIntegerの長さが等しくないといけないのにそれを崩した。 まぁ64Bit時代には8バイト整数にしたいのはわかるけど、 そうなると倍精度がRealになって、倍精度が4倍精度になってハードウェア対応せずで憤死する。 https://ideone.com/m11vQN こんな感じかな? program test2ch implicit none real(8) :: a(1) real :: b(2) equivalence(a, b) b(1) = 4.2e-2 b(2) = 0.0e0 print *, minval(a, dim = 1, mask = a > 0.0) end program test2ch 実行結果 5.070575254129006E-315 >>792 ideoneってfortranいけるのかw 変数に値が入ってるかどうかの判断ってどうしてる?ポインタとか使わずになんかNull かどうか?っての判断できんのかね? ちなみにgfortran 4.2 でDebian 8.0 64bit版での話なんだが。 >>794 ?? ASSOCIATED とか ALLOCATED じゃダメなのか? 普通の変数の場合はどうしようもないよな。 >>795 >>>794 ?? >ASSOCIATED とか ALLOCATED じゃダメなのか? 配列やらポインタ使えってこと? >普通の変数の場合はどうしようもないよな。 やはりそうなのかね?値がない場合をやって見たら、0.00000って表示されたのには吹いた >>796 変数について何か勘違いしてないか??? ただどうしてもというなら、F2003ならスカラーのALLOCTABLEというのがあるので それを使えばいい。 >>797 多分何か勘違いしてるかも。 俺の意識では、変数という箱に計算された数値データが格納されるってイメージなんだよなぁ。 まったくの初心者なのですが質問失礼します f77形式で書かれたプログラムをf90形式に変換した所plplotという描画用プログラムがエラーだらけで動きません 具体的には、「関数plwid に対する定義されてない参照です」のようなメッセージがいっぱいでてきます どうしたらよいのか教えていただけませんか?お願いします >>791 すみません補足します OSはLinux beanでコンパイラはgfortranです >>799 もとのプログラムはf77で正常にコンパイルできてるの? gfortranでそのままいけるやろ Fortran未だに使ってる人いますか? やっぱり昔に構築しちゃった遺産をそのまま使う方ばかりですか? 天文学の計算で有効数字が16桁以上で計算したいものが あり、C/C++では桁数の関係で微妙なので、Fortran の4倍長精度を使って計算しています。 64ビットあるいは80ビットでなくて128ビット で計算できるのが有りがたいです。 >>803 なるほどご丁寧にありがとうございます そういった分野があるんだと勉強になりました >>803 補足します。 NASAが太陽・月・冥王星を含む惑星の位置を計算 するための基礎データを発表しているのですが、 そのデータがたとえば 0.149597870691000015+09 という有効数字18桁で当れられて います。 この一定間隔で与えられたデータを数値積分して 位置を計算する必要があります。 C++などのlong doubleでは、有効数字が16桁程度 なので、fortranの4倍長kind(16)を指定すると、 三角関数も4倍精度で計算でき、安心できるわけです。 ソフトウェアに興味なくて、ほとんどプログラムやったことない学生が、 専門分野の研究に必要になってから勉強を始めて、曲りなりに必要なプログラム 書けるようになるのが早いのはやっぱFortranだな。 余計なことを覚えなくていいし、行列の添え字とかが(1から始まる、カラムメジャー等)、 教科書・文献などの数学の常識に近い点が良いらしい。 式とプログラムで表記が同じである必要は全くないが、 ある程度は形式を保っていないと焦点がボケてダメなようだ。 ソフトウェアの板でいうと叱られるかもしれないが、 時間かけるならプログラム言語の勉強するより専門分野の勉強する方がいい。 maxvalを使って上から2番めに大きいものなど抽出したりできませんよね? 挑発されてるようで不快だが 配列に同じ値がないか、重複を排除した2番目に大きい値 (例えば配列a=(/1, 2, 5, 3, 5/)なら3)を返してほしいなら maxval(a, mask = a < maxval(a))でいい 配列を降順に並べた時の2番目の値(上の例なら5)を返してほしいなら maxlocで最初の最大値の位置を特定して、それを除外した配列のmaxvalをとる >>808 ありがとうございます。書き方悪かったですすいません・・ 今のプログラムがスマートに書るようになりそうで大変助かりました もしかすると、3番目とかなら b=maxval(a, mask = a < maxval(a)) !b=2番目に大きい c=maxval(a,mask=a<b) !c=3番目に大きい で良いでしょうか、試してみます a(i,j) b(j,k)という変数があって、 maxval(a(i,j+5:j+10)) - b(j,k) という計算をしたいのですが、結果がおかしくなります。 もしかするとmaxvalを使って四則演算するときは配列が同じものを使用しないといけないのでしょうか 次のようなプログラムを試しに走らせたところ、 ファイルの作成には成功するのですがファイルの読み込みでセグメントエラーが出ます。 原因が分かりません、教えてもらえないでしょうか。windows7, 64bit, gfortran を使用しています。 program fileIO implicit none integer i, j, k open(17,file='mydata.dat') write (17,*) 100, 200, 300 write (17,*) 400 write (17,*) 500, 600 close(17) ! 同じファイルを今度は読み込み用にオープンする open(18,file='mydata.dat', status='old') read (18,*) i, j, k print *, i, j, k read (18,*) i print *, i read (18,*) i, j print *, i, j close(18) end program fileIO >>813 エラー内容書いて linux のgfortran 、intel fortranなら普通にいけるが 次のエラーが出ました。 Program received signal SIGSEGV: Segmentation fault - invalid memory reference. Backtrace for this error: #0 ffffffffffffffff #1 ffffffffffffffff #2 ffffffffffffffff #3 ffffffffffffffff #4 ffffffffffffffff #5 ffffffffffffffff #6 ffffffffffffffff #7 ffffffffffffffff #8 ffffffffffffffff #9 ffffffffffffffff #10 ffffffffffffffff #11 ffffffffffffffff #12 ffffffffffffffff #13 ffffffffffffffff #14 ffffffffffffffff #15 ffffffffffffffff #16 ffffffffffffffff #17 ffffffffffffffff #18 ffffffffffffffff Window7,64bitのgfortranを使ってコンパイル実行して みましたが, 100 200 300 400 500 600 と出力されて無事終了しました。 ちなみに,gfortran64のVersionは4.9.2です。 ソフトのバージョンは gfortra,64bit, ver 5.1.0 のおそらく最新版です。 とりあえず別のコンパイラを試してみます。 FTN95 でうまくいきました やっぱり gfortran ってクソだわ ファイルggshoki.f90に、800成分の配列を返すサブルーチンggshokiを書き、他のファイルと一緒にコンパイルしたところ、 ggshoki.f90:1:20: subroutine ggshoki(Z(800)) 1 Error: Unexpected junk in formal argument list at (1) というエラーが出てしまいました。 どう直せばいいのでしょうか。アドバイスお願いします。 上げてしまいました、すみません。 OS:Windows8(64bit) コンパイラ:gfortran バージョン:fortran90 です。 >>819 subroutineの内部で宣言するなら書き方が違うはず 引数で宣言するより別の行で宣言した方が見やすくない? とりあえず自分はこんな感じで書く https://ideone.com/HCzWB6 >>822 リンク先のように書いたらうまくいきました。 自分のプログラムの他の部分も確認したところ、配列の書き方が全て間違っていました(配列A(1:N)をA(N)などと書いていました)。 ありがとうございました。 教えてください。 サブルーチンに渡された配列引数2つが同一かどうか (値が同じかどうかではなくて、値を格納するアドレスが同じかどうか) を確認するすべはありますでしょうか…? ポインタとか使えるのでしょうかね?よく分かっていません。 自己解決してしまいました… program test implicit none real(8)::a,b a=1 b=2 call sub(a,b) call sub(a,a) end program subroutine sub(a,b) real(8),target::a,b real(8),pointer::p1,p2 write(*,*) '=====',a,b p1=>a p2=>b if(p1.eq.p2)then write(*,*) 'identical' else write(*,*) 'independent' end if end subroutine いや、すみません間違ってました。値を比較してるだけみたいです。 どうしたらいいんだ。 (日記みたいになってしまってですまんです) 最近出た『FORTRANハンドブック』 買ったほうがいいかな? ifortです。associated(pointer,target) で行けそうなんですが、 targetの変数にopitional属性がついていて… ><という状況です gfortranならlocでアドレス取得できるの確認した なんか独自拡張みたいだが、ifortにもあるよね module内のcontainsのところに書いているfunctionをincというフォルダのsample.f90にまるごと持って行き、 include 'incl/sample.f90' としたのですが、moduleに書いていた時はは参照できていた変数が 定義されていない参照 となりコンパイルできません。 functionまるごともっていくとかやったらいけないものなのでしょうか? >>831 内部関数を別ファイルにするなら注意が必要 includeを書く位置によるけどエラーになるなら外部関数扱いになっている 内部関数はメインプログラムの変数も参照できる 外部関数の扱いになるとメインの変数、他の内部関数、サブルーチンが参照できなくなる だから、使っている変数や関数、サブルーチンを確かめないとエラーになる 解決方法はいろいろあるけど変数だけなら引数で渡せば使える containsの後にinclude文を書けば内部関数扱いになるからそのまま使える ちなみに、includeは廃止予定とかじゃないけど非推奨らしい http://www.nag-j.co.jp/fortran/tips/tips_AboutInclude.html http://www.mri-jma.go.jp/Project/mrinpd/coderule.html >>832 詳しく教えて頂いてありがとうございます。試してみようと思います。 includeってもう非推奨なんですね。代替はmoduleで分割とかできるのかな include以外のやり方も考えてみます >>825 Fortranって規約では、引数に番地の重なる変数や配列を送っちゃ駄目じゃなかったけ? まぁ大抵のコンパイラは無警告で通すけど。 昔だとWATFORなんかが文句を言ってきた。今だとNAGあたりがなんか言いそう。 >>830 loc 相当を規格内でやるには c_loc と transfer で代替するはず。 Fotranで作成された古いプログラムをVBAに移しているのですが 符号がついていないためIF文の解釈がよくわかりません。 どなたか教えて頂けないでしょうか。 IF(J-K) 2,3,2 3 B(J)=1./Y C(J)=1. GOTO 4 2 B(J)=-A(K,J)/Y C(J)=A(J,K) 4 A(K,J)=0. >>835 IF (L) a,b,c X:負 go to a X:0 go to b X:正 go to c >>836 ご回答ありがとうございました。 助かりましたm(_ _)m >>835 >>836 いわゆる計算型go toはもう忘れられいるのですね。 >>838 私が素人というのもあるのですが、いくつかのFortranのHPみてもIF文の説明には 入っていませんでした。 >>869 ただしくは、算術IF文というものです。あるサイトの解説です 古い書き方に算術IFというものがあります。 この書き方はFortranでは廃止予定機能ですが古いプログラムには見かけられる書き方です。 算術IF文は、与えた式が0より小さい場合に最初の文番号へ、 0の場合は2番目の文番号へ、 0よりも大きい場合には3番目の文番号にジャンプします。 if ( 式 ) 文番号1, 文番号2, 文番号3 例) i = -1 if (i) 100, 200, 300 ! 100へジャンプします 古文読解みたいなもんよ。 新たに使うことは無いが、昔のプログラム読む為の教養みたいなもん? アセンブラから進化したと思えば、まぁこんな命令ありがち感はある。 ある参考書にあるプログラム例を映したのですが、実行するとエラーが出ます。内容が外部ファイルへの出力関係なので早急に解決したいのでよろしくお願いします。 プログラム integer :: n, i, j, fi = 10, fo = 11 open(fi, file = 'input.d') open(fo, file = 'output.d') read(fi, *) n close(fi) if(n < 3) stop 'stop, n < 3' d = 10.0d0 / dble(n - 1) do j = 1, n y = -5.0d0 + dble(j - 1) *d do i = 1, n x = -5.0d0 + dble(i - 1) *d z = sin(x) * cos(y) write(fo, '(3e12.4)') x, y, z enddo write(fo, *) ' ' enddo close(fo) エラーメッセージ Program received signal SIGSEGV: Segmentation fault - invalid memory reference. Backtrace for this error: #0 ffffffffffffffff #1 ffffffffffffffff #18まで同文 OS:Windows7(64bit) コンパイラ:gfortran よろしくお願いします 申し訳ありません。確認したところ コンパイラはtdm64-gcc-4.6.1です。 再び申し訳ありません。 gfortranのverを落としたら普通にできました。何度もすみませんでした。 intelコンパイラのDAALをFortranから なにかしらの形で呼び出してうまくいった方いませんか? fortranで簡単なguiウィンドウ作れたりしますか? ウィンドウがあってこのボタンを押すと〜〜のサブルーチン実行のような・・・ >>846 visual fortranにRADがあったような気がする けど、Fortranで計算部分をライブラリ化しておいて 別の言語で作ったGUIで呼び出す方が一般的だと思う >>847 ありがとうございます やっぱり流行りの言語も使ってみたいと思います 基本的な質問かもしれませんがfunctionとsubroutineで作るのってどう切り分けたらよいのですか? >>849 functionを使うのは、返値が一つと自明な(かつ明示したい)ときだけかな。 >>850 ありがとうございます 計算速度は関係ありませんか? 例えばファンクションのほうがその度に呼び出すために計算速度は遅くなるとかありませんかね・・? 差は感じたことないな 気になるなら簡単なテストプログラム作ってみたら? 中身が分からないunformattedで出力されたファイルを読むにはどうすればいいですか? ACCESS='STREAM' でオープンして嫁 詳しくはマニュアル検索検索 >>849 function は副作用(PURE の時)がないとき、それ以外なら SUBROUTINE が基本かな。 コンパイラの最適化の観点から、数学的な意味での関数になっているときに使うのがいい。 今二分法のプログラム書いているんだけど、うまく収束しなくて困ってるのでここで質問させてください ある区間[a, b] の間に解があるとして、f(xsol) =0となる点を見つけようとしてます。 関数f(x) は数値計算によってしか求められない(xの多項式では記述できない)とします。 x -> xsol に近づいていると思うのですがどうしても0 に漸近しません。 収束条件は 10^{-1}程度の荒いものでも収束しません。 考えられる原因の1つとして情報桁落ちかな?と思いましたが回避する方法はあるでしょうか? ある程度計算を進めると、区間[x1, x2]において、その中点 (x1+x2)/2の値が一定となってしまいます。 >>857 後出しで申し訳有りません。 変数は全て倍精度で設定しております。 >>857 real(16) と宣言して、8倍精度にしたらどうなりますか。 >>853 >>856 返信おくれてすいません。 勉強になりました。一つ出力でpureな時はファンクションを使うようにします。 >>859 今4倍精度に宣言して計算終わったところです! 一定になるところは変わりましたが、計算を進めるとやはり中点が一定になります。。。 >>859 ,861 ちょーーー!! 8倍精度とか16倍精度と違うから! 普通はバイト数だから8で倍精度、16で4倍精度。 まぁ数値はベンダー依存で規定されていないから、あんたらのコンパイラが 8倍精度や16倍精度なのかもしれないがさw そもそも二分法の場合必ず半分になるんだから、まともなら x1=x2 にならないはずがない. ならないとすればプログラムが間違っているか、関数値の正負が x1 と x2 の間で 複数回反転しているかのどっちかだろ。つまり与えた区間の初期値が間違っている。 まずグラフを書かせろよ。 適当に数値いれて手で方眼紙にプロットしろ。話はそれからだ。 >>857 関数f(x)がもともと収束しない形である可能性はないのか? >>863 すんません、完璧勘違いしてました! やはり4倍精度で正しかったですm(_ _)m 勉強になりましたm(_ _)m >そもそも二分法の場合必ず半分になるんだから、まともなら x1=x2 にならないはずがない. >ならないとすればプログラムが間違っているか、関数値の正負が x1 と x2 の間で >複数回反転しているかのどっちかだろ。つまり与えた区間の初期値が間違っている。 初期値問題ですか。。。。 >まずグラフを書かせろよ。 >適当に数値いれて手で方眼紙にプロットしろ。話はそれからだ。 グラフなんですが、f(x)が非線形なので数値計算のみでしかもとまらないです。 >>865 沢山の点で計算してEXCEL等でプロットすればいいのでは。 >>865 まずは4次のルングクッタでグラフ描いてみてはどうだ? fortranだと変数がからかどうか判定できないんだっけ? 空だと 0.00が代入されんのかな 空ってなんだ? 初期化されていないということか? Fortranでは初期化されていない変数の値は不定だぞ。ごみが入っている。 0.0は初期か忘れに気づきにくいから、むちゃくちゃな値が入っていたほうが親切。 allocatableがallloctaeされているかいないかならallocated関数かな。 >>870 allocatable で配列宣言してないとそれ使えないよね? 例えば、 program main implicit none double precision:: a, stat do read(20,*,iostat=stat) a if(stat<0)exit enddo rnd program main fort.20 ファイルの中身が空(null)だとしたら変数aにはゴミが入るわけよね? 変数aに何の数値も代入されていないと自動的に確認するためにはどんなコーディングが必要だろう、この場合。 Fortranのレベルでどうこうではなく、Undefined Behavior Sanitizerでも使えばいいんじゃないの >>873 それはオプションかな? 今回の問題とはちょいと違うのだ いまさらfortranで機械学習とかディープラーニングライブラリ作って公開する猛者いませんか? いたら面白いのになあ iMacだがLAPACKのコンパイルが上手くいかない。MacBookAirの時は上手く言ったのだが誰か教えてくれないか? >>872 Fortran2003 ならスカラーの allocatable もある。 I/O では無理だが、例えば Function からの代入ならば、希望のことはできる。 スカラーへの allocatable 変数が返り値の Function からの自動再割り付けで、 右辺の関数の返り値が空なら、左辺の allocatable スカラーが allocate されないし、 値をもっていれば NULL だろうとallocate されるので allocataed 関数を使えば判別できると思う。 Fortranって何を使ってデバッグするんでしょうか 数値計算するときの刻み幅の決め方が難しすぎるなぁ 等幅だとものすごい配列使うからメモリがオーバーフローするしなんかいい方法ないすかね? てか、刻み幅に関する詳しい本とかないのかなぁ >>881 森口繁一先生の 『計算数学夜話』 に、「刻み幅の自動選択」 という話が掲載されていたはずです。 変化がなだらかな区間は刻み幅を広く、 変化が急な区間は刻み幅を狭くするのを 自動化するという話です。 >>882 ありがとうー うー、でも手に入らないぽいなー((((;゚Д゚))))))) 桁の大きなものと桁の小さなものが混じった数値計算をするとき、規格化するのは常識だと思うんだが。 ある変数の取りうる範囲が極端に振れる場合(例えば、1d-20 < x < 1d8) だとどうすりゃいいんやろか。 >>885 それ教授や先輩にも言われたんですかまったく意味わかりませんでした。 刻み幅で対数????といった感じです。 logx(i+1)-logx(i)=刻み幅 ということですか? ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.1 2024/04/28 Walang Kapalit ★ | Donguri System Team 5ちゃんねる