くだすれ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/ ん、コンパイル別々にしてリンクすればいいとおもうよん。 f77の継続行記号(6ケタ目の空白以外の任意文字)を継続前の行の最後の & に置き換える だけで、原則f77はf90で解釈できるので、 そこだけいじって同じファイルに追加しちゃうという手もあるけどね。 呼べる。 module f77module contains ..... ここにサブルーチン、関数ならべる。 .... end module f77module 固定フォーマットの独立したファイルにして分割コンパイルすればよし。 旧形式のコードて今でも普通に書かれてるの? 仕方なく再利用してるだけで、新しいコードは全部新しい文法で書くべき? > 旧形式のコードて今でも普通に書かれてるの? わしゃバリバリ固定書式で書いている。 左7つ開けとかないとムズムズするのでw > 新しいコードは全部新しい文法で書くべき? 書くべきだとおもう! 思うが・・・・ >>114 ということは、その処理をすれば固定形式と自由形式の混在したソースコードも コンパイルできるということですか? 新しい文法使ってもそれはそれで保守できるかという 自由形式として解釈できない固定形式の文法が継続行の扱いくらいかと 素直に固定形式のファイルと自由形式のファイルと分けた方が良いと思うズラ f77時代は1個のファイルにまとめた方が、引数チェックや最適化のメリットが あったが、f90以降は、MODULEとか使えば、分割コンパイルにそれほど害はないズラ インテルだと ifort -ipo でファイルがバラバラでも最適処理してくれるよね。 >>122 ifort -ipo インテルの中に はじめの一歩の 母ちゃんのファンがいるに違いない 年内にインテルFortranの更新来ないのかな?二か月に一回の周期来てんだが。 block..end block を早く入れて欲しいわ。 たまに loop index を局所的に確保したい。頭部の宣言部が重くなりがち。 下記のようなループの外でopenしてループの中で書き足していくプログラムを書いているのですが, ifortでコンパイルした場合,実行の途中でもファイルが更新されていくのですがpgiでコンパイルした場合はプログラム終了まではファイルが更新されず, プログラム終了時に全部書き込まれます.pgiでコンパイルした場合でもプログラムの途中で適宜ファイルが更新されるようにできるのでしょうか open(1000, file='data.dat') do j = 1, N write(1000, *), j enddo close(1000) linuxでfortran 77のコンパイラってありますか? gfortranというのを使うらしいのでそれをインストールして試したのですが知人に貰ったfortran 77のコードがコンパイルできませんでした >>129 gfortranは77に対応していません。 フリーってことでおk? fortran77対応のフリーのコンパイラはg77が有名かな。 linuxならintel fortranもnon commercial版になるけどフリーであったはず。 研究や企業での利用はできないから注意。 個人的にはfortran77をいつまでも使っていないで、 90に書き換えて、折角インストールしたgfortranを使った方が良いと思う。 書き換え方は拡張子を変えるのと、改行の&ぐらいでとりあえずは動くでしょ >>130 g77でコンパイルできました ありがとうございます gfortran って f77 コンパイルできないの? f90 は f77 完全包括しているし、廃止事項をホントに廃止している 処理系はめったにないからオプション変えれば行けるんでね? 誰かおしへて。 はじめからコードを倍精度で書くのと、コードは単精度でかいて倍精度はコンパイラのオプションに任せるのってどっちがやってる人多いのかな。 後者のメリットはコードがすっきりすることくらいか。 AUTODBLは、べた書きの定数の桁がどう扱われるのかよく分からんとか 微妙な精度の問題が気になってIMPLICIT DOUBLE(A-H,O-Z)に乗り換えたわ。 あと、昔のプログラムだと整数とからんだCOMMONやEQUIVALENCEの整合が狂って 謎な挙動をしたりするから困る。 >>132 g77の拡張機能つかってるコードをそうと知らずにgfortranでコンパイルしようとして互換性ないと勘違いした >>133 以前、同じことが気になったので、 中くらいの長さ200行ぐらいの単精度コードを手でw 倍精度化したのと、 コンパイルオプションで倍精度化したのを比べたことがある。 gfortran と ifort ではそれぞれで 実行バイナリが冒頭の一部分(コンパイル時刻?)以外は同一だった。 なので自作コードだけなら、違いはないか気にならない程度だとおもう。 third party library で 単精度と倍精度でサブルーチン名が違う場合があるので その場合にどうなるか、はしらない。 あと、OpenMP で並列化したやつもまったく同じだった。 MPI で並列したやつはまるで駄目だったので これは泣く泣く手で倍精度に揃えたw third party というかソースのない、かつ組み込みでない関数/サブルーチンは 変換できないし、規定されていない方の値を渡すと意味不明な挙動になるぞ。 なお対応する interface 定義が提供される module を use して総称名で呼ぶと コンパイル時に型にあった引数定義のサブルーチンが選ばれるようになる。 MPI はこういうトリックとは関係なく、1要素の大きさを渡すあたりに工夫が要るかと。 知り合いのMPIのコードは倍精度はコンパイルオプションに任せてたな mpi_float を mpi_double に置き換えてくれるのかな? MPI で単精度か倍精度が気になるのはその点くらいだよね emacsのfortranモードについてなのですが、 変数宣言のあとに「::」をつけると、変数名に色がつくのが気に入っています。 ですが、改行すると色わけされません。 解決方法はありますでしょうか? 例、 integer :: i& ←色がつく ,j ←色がつかない >>141 継続行を使わずに2行に分けて書くのはダメなの? integer :: i integer :: j >>142 今はそれで対応しているのですが なんとなく、同じグループの変数はまとめておきたいなと思いまして・・・ >>141 emacsの事は良く知らないけれど、f90.el内の ;; Variable declarations (avoid the real function call) の次の行を編集すれば良いのでは? あとemacsスレの方がレスが付き易いかも知れないね >>144 返信遅くなってすみません。ありがとうございました。 ずっと、fortran90メインで書いてたけど、Javaを触ってみようと奮闘したら、 訳わからん。書籍も分厚いのに、全部書いてある本ってあるの?少し違う事を しようとしたら、必ずネットで調べらなあかん。fortranなら簡単に書けるのに。 Javaって新しい言語だから素人にもある程度優しいもんだと思ってたのは間違い なの?自分がアホなんだろうなあ。プロの人ってすごいなあと、自らのアホさ 加減にへこむ日々。fortranで簡単にGUI使えたらJavaなんて要らないのに。 アホな書き込みすいません。 ああああああああ、だめだw。いらつかない。いらつかない。 Fortranとかいうアホ言語使ってるからそうなるんだ C++を使いなさい C++が使えるようになればJavaなんか簡単 GUI 書くのはどの言語でも(記述量はともかく仕様の理解に)手間だろ…。 >>147 ベターCじゃなくて真面目にC++ならな >>146 なんでやねん 俺にすればJavaの方がFORTRANよりずっと簡単に思えるぞ C#もだいたい似てる 使うコンピュータがメインフレームならJava、WindowsならC#がGUIが一番楽 というかメインフレームにはMonoすらない事が多いし C#はDelphiの流れを受け継いでいるのとJavaやC++の良いとこ取りしている ある意味卑怯な(?)言語なのでGUIはこれが一番早く完成する ファイルを読み込んでcharacter型の変数に代入しようとしています。 一行の文字数が不定なときはどうすればいいですか? あらかじめ要素数をおおきめに用意する以外でおねがいします。 コンパイラーはintelの9.0です あと、intelの非商用のコンパイラってもう配布されてないんですか? >>150 //www.nag-j.co.jp/fortran/FI_18.html#AUTOTOC_18_4 >>151 linux用ならnon-commercial板があると思うが 1文字づつ読んで改行まで貯めこむしか無いんでないかな。 IVF9.0では無理だと思うがF2003なら、可変長文字列ではなく文字配列ならIVF9でも可かな。 program test implicit none character :: ch character(:), allocatable :: buf buf = '' do read(9, '(a)', end = 999, advance = 'no', eor = 8) ch buf = buf // ch cycle 8 print *, buf buf = '' end do 999 stop end program test >>152 non commerical で検索したら見つかりました ありがとうございます >>153 buf=buf//ch は代入するたびにallocateしなおしてるやつですか intel の最新版はF2003に対応しているみたいなので そっちを使ってみます >>154 >は代入するたびにallocateしなおしてるやつですか そう。大量で負荷が重いなら大きなbufferを取るしかない。 IntelFortranの場合F2003文法はデフォではOFFになっているので standard-semantics をONにする必要があるかも。 配列の場合 buff = [buff, ch] で配列要素数を拡張していけるが、この場合はオプション必要。 実行時間を計測することはできると思いますが 使用したメモリの最大値を計測することはできませんか? コンパイラはintelです Linux なら ps をじっと眺めているw Windows なら task manager のグラフを眺める。 include文やuse文で読み込むインクルードファイル、モジュールファイルを 別ディレクトリにおいてコンパイルしたいのですが、 インクルードパスの設定方法がわかりません。 コンパイラはifortです。 ifort -I*** ***に絶対パスを入れたり、相対パスを入れたりしたのですがダメです。 そもそも、-I/でタブ補完しようとすると -I/ is not found.と出てきます。 何か別の設定が必要なのでしょうか? インクルードファイルがあるディレクトリは、カレントディレクトリの中にあります。 fortranの出力指定子でマニアックなものまで全部のってるサイトを教えてもらえないでしょうか 例えば0.005を↓のように出力する指定子を探しています 5.000000000000000-3 >>159 EN(工学用)なら3乗おきに出力できたはず 0.005なら単純に科学系のES記述子でもできる いつから在るか知らないけど、最近の本(自分が買ったのは5年前)には普通に載ってたよ Webサイトなら"Fortran 編集記述子"で検索すれば色々出てくるけど、 自分の環境で使える記述子を全部知りたいならコンパイラのリファレンスが一番確実 さっき始めたんですがわからないので教えてください あるモジュールにサブルーチンが二つある時にこの二つのサブルーチンを違うファイルに記述することは出来ますか? C++でいう名前空間のように分離できるか?ということです 名前空間を分けたいなら、まぁmoduleを二個使え。 USEでエイリアスをつけろ。 どうしてもというなら、一個のモジュールを二個のファイルに書くことは、 includeを使えば出来ることはできる。 またFortran2008で導入されるsubmoduleを使う手も考えられる。が、実装している 処理系はまだないと思う。 Fortranのcharacterって文字コード決まってたりする?環境依存? 内部コードは環境依存。 というか昔はIBMのEBCDICこそが本物コードでASCIIは安物ミニコンとかのパチモン文字コードだった。 ANSI FORTRAN77の時に内部コードの他にASCIIコードに対応させる関数が導入されてる。 スレチかもしれないけど リスト構造を無限ループで回してるところを openmpで並列化したいんだけどできます? リスト構造といっても色々あるから答えようもないぜw Fortranはデータパラレルには強いがタスク・パラレルは弱いけど、 OpenMPの新しい版ではタスク・パラレルできるから リスト構造で枝分かれするところでタスク分割すればいいんでね? 順序入れ替えが無い線形リスト構造なら、配列に直せば元々高速になるし、 並列化の余地も大いにあると思う。 print '(g20.12)', 1.d-100 とすると 0.100000000000E-99 と返してくれるのですが, print '(g20.12)', 1.d-101 とすると 0.100000000000-100 のようにEが消えてしまいます. これだとプロットのソフトによっては0.100000000000-100を-99.9と解釈してしまい困ってます. どうすれば3桁以上の指数部分も正しく書けますか. コンパイラはifortです. >>168 こんなかんじかな。 program p implicit none integer :: i1,i2 real(8) :: d1,d2 character(10) :: s1 d1=-1d-105 i1=log10(abs(d1)) d2=d1*10d0**(-i1) write(*,"(g25.16,f25.15,a)")d1,d2,"E"//i2s(i1) contains function i2s(ival) integer, intent(in) :: ival character(int(log10(dble(abs(ival))))+2) :: i2s character(12) :: s1 write(s1,"(i12)")abs(ival) if(ival.ge.0)then i2s="+"//s1(12-int(log10(dble(abs(ival)))):12) else i2s="-"//s1(12-int(log10(dble(abs(ival)))):12) end if end function end program >>168 '(g20.12e3)'で指数部の桁数を指定するとか >>170 そんな仕様があったのか。知らんかった。 f90って継続記号は行頭ではなく行末でないといけないんですよね? 例えば、 equation = A& + B& + C みたいな式があってCの寄与をみるためにコメントアウトするとき たまにBの後ろの&をコメントアウトしわすれて面倒だったりしませんか? 絶対文頭につける仕様のほうが便利だと思うんですが・・・。 セミコロンで文末にできた気がする equation = A& + B& ; ! + C B から継続→文末、C の除外 10.000 100.00 1000.0 100000 浮動小数点を上記のように書き出したいのですが どのように書式を指定すればよろしいでしょうか >>176 f?.* を使ってください。 ?は全体の桁数、*は小数点以下の桁数。 私も質問です。 サブルーチンの引数に配列を使ったときに、実引数と仮引数でサイズのチェックが行われるような書き方、 あるいはコンパイルオプションはありますでしょうか? 例えば、実引数がa(0:imax)で仮引数がb(1:imax)のとき、エラーが出ずにコンパイルが通ってしまうことがあります。 その場合、実行結果がめちゃくちゃになるのにエラーが出ないのでデバッグに苦労しています。 内部サブルーチンのときはコンパイルエラーが出ますよね? 外部サブルーチン、あるいはモジュールでもエラーが出るようにできますでしょうか? あるプログラム単位は、外部サブルーチンがどんな引数を取るかは知らん。 だから引数の整合性を確認するのは、プログラマの責任だった…のが FORTRAN77 Fortran90 から、interface ブロックで、外部サブルーチンがどんな引数を取るつもりか 定義をプログラムに書けるようになり、コンパイラのチェックを受けられるようになってる。 これだけではあまり意味はないが、module で定義を書き、その内容を use 文で 取り込むことで、複数ファイル間での一貫性が取れる構造となる。また、モジュール内 サブルーチンはわざわざ interface を書かんでも use されたプログラム単位からの 参照に対してチェックがかかるはず。 ちなみにインテル Fortran なら /warn:interface でうるさく言ってくるようだ。 >>179 ありがとうございます。具体例をあげます。 module_Aのなかに、サブルーチン1とサブルーチン2がcontainsされています。 module_Bのなかに、サブルーチン3がcontainsされています。 ケース1、 サブルーチン1でuse module_Bとして、サブルーチン3を呼び出します。 実引数はmodule_Aで宣言しており、x(0:imax)です。 仮引数はサブルーチン3で宣言しており、intent(out)属性をつけてx(1:imax)です。 この場合、コンパイルしてもエラーが出ませんでした。 つづき、 ケース2, サブルーチン1でサブルーチン2を呼び出します。 実引数はintent(inout) :: y(1:imax)で仮引数はintent(in) :: y(0:imax)です。 この場合もエラーが出ません。 コンパイラはifortです。 できれば、これらのケースでのinterfaceの使い方を教えていただきたいです。 ftn95 で、以下のエラーメッセージの原因がわかりません。 (メッセージの意味ではありません) Error 29, Call to missing rotine : _EXSUB at 0x00******. 主プログラム(main.f90) program main use interface_mod implicit none integer :: a,b a=3; b=5 call exsub1(a) call exsub2(b) end program 外部サブルーチン(exsub.f90) subroutine exsub1(r) implicit none integer, intent(in) :: r real(8),dimension(r):: w print *,w end subroutine subroutine exsub2(s) implicit none integer, intent(in) :: s real(8),dimension(s):: x print *,x end subroutine (うえのつづきです) インターフェイスモジュール(ifmod.f90) module interface_mod interface subroutine exsub1(r) integer,intent(in)::r end subroutine subroutine exsub2(s) integer, intent(in) :: s end subroutine end interface endmodule interface_mod 質問です。 計算の結果を.datファイルに書き込むプログラムを作成したのですが datファイルの中身を確認すると文字化けしています。何がいけないのでしょうか? OSはWindow7 64bit、コンパイラはFortran90です。「あらきけいすけの雑記帳」を参考にしました。 プログラムすべて乗せるとちょっと長いので関係有りそうな部分だけ。 最初はこのように宣言 open(1, file='1.dat', status='replace',access='direct',recl=4) その後doで回しながら計算結果を書き込む write(1,rec=(it-1)*39*39+(iz-2)*39+(ix-1)) p2(ix,iz) direct access なら内部コードで書かれるんだから当然じゃ >>182 そこに張られているものは問題ないと思う。 エラーメッセージはサブルーチンexsubが無いと言っているので、 call しているプログラムが exsub1,exsub2 になっておらずexsub になっていると思われる。 たぶんファイルのセーブ違い、コンパイル違い。 インターフェース+野良サブルーチンにするより、 サブルーチンは module に入れて module を use するのがふつう。 インターフェースは、外部ライブラリとか、関数引数みたいな場合以外は 出番なくてよし。 >>180-181 最新版の intel compiler ならエラーを出す。 ただし宣言元の配列の方が大きくて、サブルーチン側の配列がその中に納まるなら 問題は無いので何も警告しない。 そもそも66時代には、サブルーチン側の配列を10とかに宣言して サイズの不整合を気にしなかったし、77で整合配列が導入されても 66時代からの習慣などで、整合性は気にしなかった。 配列サイズの整合に姑根性でうるさくされると、昔のプログラムが動かなくなるので 皆困る。おおらかに行こうぜ! 気になるなら、仮引数の終端の方を宣言しなければ、自動でコンパイラ様が 適宜取り計らってくれる。 real, intent(in) :: x(0:) みたいな。 >>184 書いたファイルの中身が見たければアクセスとか指定せずデフォでいけ。 (シーケンシャルアクセス) write文は自由フォーマットwrite(1,*)で。 >>185 ,>>186 ご指導ありがとうございます。 fortranは初めて触った言語で、これで正しいのか不安だったので助かりました。 direct access は、大量のレコード長(データの長さ)が等しいデータを 書き出しておいて、読み出し/書き換え時に、ランダム位置に直接そのデータを 読みに行くときに使うもの。 普通に不定長のデータをファイルにだらだら書き出して、読み出す時も前から順番に たらたら読み飛ばしつつ、欲しいデータを探して行くときは、 デフォルトのシーケンシャル・アクセスファイルでいい。 また、人間がファイルを覗いたりするなら、フォーマットを指定して/自由形式にして 読み書きすればいい。 write(1, '(2f15.7)') x,y write(1, *) x,y ファイルサイズを小さくかつ高速にアクセスしたいときは、 write文でフォーマットを指定せず、内部表現で読み書きするが、 write(1) x,y >>186 ご指摘ありがとうございます。U島氏の本にて学習中の身です。 ソースを見直し改めてコンパイル、ビルドしましたが、 外部サブルーチンが読めないと警告してきます(もちろん実行はエラー)。 gfortranですと何の問題もないのですが・・・ 上に貼ったものは、gfortranで通ったものを試したもので、 実は、ftn95環境下では、real(8)は、real(kind(1d0))へと正されました。 ひょっとするとまだ、当方が何か見落としているのでしょうか?? >>189 手元にFTN95の環境が無いので何とも言えないが、 gfortranで行くならftn95の問題かもしれない。 1個のファイルにまとめてみたらどうかな? ただし、順番に依存するので、メインルーチンは最後に置かないと駄目だと思うが。 まぁサブルーチンをmoduleに入れた方がinterfaceも要らないし楽だと思うが。 COMPAQ VISUAL FORTRAN6.6が WIN7 32 HOMEで起動しなくなりました。WIN32 PROでも起動しないことが他にあるのですが、しつこく起動することで使える状態です。 そこであきらめてDOSプロンプトでコンパイル しようと考えています。MAIN.F SUB1.F SUB2.Fのテキスト文がある場合のリンクの方法をお教えください。コピペでまとめてやればいいのですが 細かく ライブラリ化(というのですか) していきたいもので よろしくお願いします。 具体的に 例文で書いてもらったら助かります。 CVFは先祖がDEC Visual Fortran (DVF)なので、 dfでコンパイラドライバが起動する。 df sub1.f sub2.f main.f で sub1.exe が出来上がると思う。 デフォでは実行ファイルの名前は先頭のファイル名になる。 moduleなどは先にコンパイルされている必要があるので、main program は 最後に来ることになる。 df /help もしくは-help でヘルプが出るだろう。 CVFは10年以上前のコンパイラなので、目的にもよるが 無理して使うよりは新しいのを手に入れた方がよいかもしれない。 同じプログラムでも、最近のコンパイラではめちゃくちゃ速く実行することが多い。 >>186 180です。結局、人間がチェックしないとダメみたいですね。 ありがとうございました。 >>193 正直Fortranではああいう書き方はあまりしないので、チェックにかからない。 66ならサイズは気にしないで、sub(x); x(10) 77なら整合配列で、sub(n, x); real x(n) 90なら形状引継ぎ配列で、sub(x); real, intent(in out) :: x(:) 配列を0から始めると苦難の道が待っているので、数学的要請でない限り 避けるのが吉。 4バイト整数の変数が,4バイトを超えたときエラーにならず変な値(マイナスになるはずのない値がマイナス)でそのまま計算が進んでしまいます。 プログラムのどのあたりで超えるか知りたいので,エラーで終了するようにするオプション又はデバッグオプションなどありませんか? コンパイラ : intel fortran version 12 (CentOS 5) >>195 昔のDEC Fortranにはinteger overflowの実行時チェックオプションがあったが、intel fortran になってから そのオプションは無くなった。今もないんじゃないかと思う。 最近配列サイズが4byte整数を超えることが多くなってきたので、このチェックのあるコンパイラがあってもおかしくない気はする。 gfortranとかfreeのfortranも含めて コンパイラオプションの説明を、便器を舐めるように注意深く読んで見るといいのではないか。 >>196 一応ifortのhelpでは,"整数"で検索かけてみたんですが,使える物はとくにありませんでした. 目視で全文確認してみます. ありがとうございました. 貰い物の古いコードが、グローバル変数をCOMMON文でインクルードしている形式なのですが、 そこのCOMMON文に新しく変数を付け足したところ、 >COMMON のために、オブジェクトのアライメントが型と一致していません >パフォーマンスに影響を与える可能性があります。 という警告が出ました。 変数の付け足す位置を変えたら出なくなったのですが、どういう意味かわかる方いらっしゃいますか? >>198 32bitコンピュータとか64bitコンピュータと呼ばれるように、コンピュータは ビットの塊を一括して処理する。メモリーアクセスは、0番地から32や64bit の区切りで一括でなされる。この境界をまたぐと、本来1回で読み書き できるデータに2回読み書きにいかなければならない。 そういうわけで、最近のFortranコンパイラは、自動的に境界合せをするようになっている。 ところがCOMMON文は、同じメモリー領域の割り付けだから、 コンパイラが変数の位置を勝手にずらすと、対応がずれてしまう可能性が出る。 それでアクセスが遅くなるよと警告している。 COMMON文はグローバル変数というよりも、メモリー割り付けの手動制御と 理解した方が良い。COMMONにあるのがREALとINTEGERだけの場合は、 ズレが起きることは(例外的な場合以外)ないが、文字列などがあると すぐずれて色々警告される。文字変数は後ろの方に置くのが吉。 FORTRANコンパイラではREALとINTEGERのデフォサイズが共通であるという (暗黙の?)約束がある。COMMON文での共有があるためだと思うが。 AUTODBLEをつかったりするとずれる可能性が出る。 以前GFORTRANだったかg95だったかが、この約束を破ってド顰蹙を買っていた。 はじめまして、こんにちは 現在、フォートランで数値計算をするプログラムを作っています。 今日、プログラム内で使っている配列のサイズを極端に大きくしたところ、スタックオーバーフローというエラーになりました。 解決策としては、コンパイルオプションでスタックを初めから大きくするというものがあるそうなのですが、この方法にデメリットはないのでしょうか? また、これ以外の方法で、皆さんならどのようにオーバーフローを回避しますか? >>200 サブルーチンとか関数で大きく確保しようとしたんだろ? allocatableで確保すれば、ヒープ領域に取られるのでだいじょぶ。 次のようなデータをファイルから読み込みたいのですが,read文と書式をどう書けばよいか教えてください. データの並びは (親核種)(娘核種)(娘核種の比率)(孫核種)(孫核種の比率)(ひ孫核種)(ひ孫核種の比率)… となっており,何世代まで子孫の核種があるかはファイルを読むまで分からないとします. ---------データの例(はじまり)------------- Pb-202 Tl-202 1 Pb-210 Bi-210 1 Po-210 1 Pb-212 Bi-212 1 Tl-208 0.40 Po-212 0.71 Bi-210m Ti-206 1 Bi-212 Tl-208 0.36 Po-212 0.65 At-211 Po-211 0.58 Rn-222 Po-218 1 Pb-214 1 Bi-214 1 Po-214 1 ---------データの例(おわり)------------- read(unit=10,fmt='(A,100(:,A,E))') parent, ( progeny(i), progeny_ratio(i), i = 1, 100 ) このように書きましたが,Eに長さの指定がない,とエラーが出ます. 自分が分からない点は以下の二つだと思っています. 1. 任意の桁数の小数を読み込む方法がわからない 2. 一行に任意の個数だけデータが並ぶ場合のreadの仕方がわからない コンパイラはgfortranを使っています. >>204 結構めんどい。 1.任意の桁数の小数を読む最も楽な方法は、自由形式を使うことで、 空白とかコンマが区切りに入っていれば自動で切り分けてくれる。 自由形式を使わない場合は、動的にFORMAT生成する方法がある。 2.任意個のデータを読むのは、エラー上等で読み込んで、iostatで エラーコードを調べて、END OF RECORD ならおkとか。 しかし、今の場合文字列処理の方が問題。固定長ならまだやりようがあるが、 Bi-210m みたいに長さの違うのが混じると苦しい。 結局、1行ごと文字列として読み込んで、空白をトークンとして自分でパース していくのが素朴。 Fortran2003/08なら、もう少し柔軟なIOできるかもしれない。 program twochan implicit none integer, parameter :: nmax = 100 character (len = 136) :: buff character (len = 10) :: parent, progeny(nmax) real :: progeny_ratio(nmax) integer :: i, k do read(10, '(a)', end = 999) buff buff = adjustl(buff) k = index(buff, ' ') parent = buff(1:k - 1) buff = adjustl(buff(k:)) i = 0 do while(trim(buff) /= '') i = i + 1 k = index(buff, ' ') progeny(i) = adjustl(buff(1: k - 1)) buff = adjustl(buff(k:)) k = index(buff, ' ') read(buff(:k - 1), *) progeny_ratio(i) buff = adjustl(buff(k:)) end do print *, parent, (progeny(k), progeny_ratio(k), k = 1, i) end do 999 stop end program twochan >>206 専ブラインデント用引用符 実行結果 Pb-202 Tl-202 1.000000 Pb-210 Bi-210 1.000000 Po-210 1.000000 Pb-212 Bi-212 1.000000 Tl-208 0.4000000 Po-212 0.7100000 Bi-210m Ti-206 1.000000 Bi-212 Tl-208 0.3600000 Po-212 0.6500000 At-211 Po-211 0.5800000 Rn-222 Po-218 1.000000 Pb-214 1.000000 Bi-214 1.000000 Po-214 1.000000 すばらしいです!ありがとうございました. 実は,自分もほぼ丸一日試行錯誤した末にできたのですが, なぜ自分のプログラムがうまく動くのか説明できません. 教えてもらった方法をこれから読んで勉強しようと思います. gfortranで通常の宣言型を超えて桁数の上限なしの計算をしたいのですが、 質問1)GMPというのを使えば良いのですか? (既にPCに入っているとしたら、Ubuntuの場合は、どこのなんてファイル群?) 質問2)GMPを使うとして、どのようにソースを書けば良いですか? (FMLIBの場合は、最初にuse FMZMとして、型宣言の時にtype(IM)とか) 質問2)他にもっと多倍数演算に向いたツールはありますか? 質問です学校で COMMAND入力に「XX<YY.dat」という操作をしたのですがどういう意味でしょうか? >210 XXというプログラムにYY.datというデータを入力したと いうことです。 XX>YY.datとすると、XXというプログラムの出力を YY.datというファイルに出力することを意味します。 >>209 FMLIBかMPFUNでいいんでね? Fortranで書かれてるし。 >>212 FMLIBにて成功しました。ありがとう。 今までintegerしか多倍数演算できなかったんだけど、FMLIBのほうがいい。 ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる