1 名前:デフォルトの名無しさん [2006/01/24(火) 09:48:23 ] このスレッドは、他のスレッドでは書き込めない超低レベル、 もしくは質問者自身何が何だが分からない質問を勇気を持って書き込むスレッドです。 FORTRAN使いが優しくコメントを返しますが、 お礼はFORTRANの布教と初心者の救済をお願いします。
201 名前:199 mailto:sage [2006/02/24(金) 13:05:48 ] 199,200で書いたこととは無関係に一般論的な結論を言わせてもらうが、 fortranでは宣言した配列の大きさとは無関係な大きさで配列を使うことが ままあるので、引数として渡している大きさを配列の宣言長に直すのは、 とても危険である。 FORTRANのライブラリなどでやたらと配列の寸法を引数として求められるのも、 配列は先頭要素のアドレスしか渡しておらず、そのほかの情報を一切渡していない からである。 またFORTRANでは、この性質を大いにプラスに利用しているので (というかこれが無いとまともな実用的なプログラムが書けない)これを非難するのは お門違いである。 FORTRAN90では、配列の次元や寸法も渡しているがその性で、>>200 で書いた ような列ベクトルを渡す時に、余分な処理が必要になって速度が低下する。 こういう時にFORTRAN77式の先頭アドレス渡しの簡潔さが心地よく感じられる。
202 名前:198 [2006/02/25(土) 00:14:20 ] >>199 丁寧なご解説、痛み入ります。 なるほど、配列に関する色々な情報ではなく、配列のアドレスを渡しているだけなのですね。 そういえば他の箇所で多次元配列が1次元の配列として処理されていたり、 首をかしげたおぼえがあります。 このあたり、移植の際には気をつけないと駄目ですね。 ありがとうございました。ご指摘の点を踏まえて頑張ってみます。
203 名前:デフォルトの名無しさん mailto:sage [2006/02/25(土) 01:49:11 ] 10年以上前の話だけど、 なんとなく入学した大学で、入学直後からFORTRAN77の宿題を大量に課せられた。 もちろん僕にはFORTRANが一体何なのかもよくわからなかった。 とりあえず、テキストをマネしながらキーボードを叩いてはみたものの、 なんでこんな勉強しなきゃいけないのかわからなかった。 正直言って、楽しくなかった。 同学部の友達が居なくて、先生も冷たくって、僕は1人だった。 結局、大学には通わなくなり、僕はその場所を去った。 その後、僕はプログラムとは無縁の人生を送ることになった。 このスレにFORTRANの宿題を持ってくる人・・・ それに対して丁寧に解説をされている方々・・・ ログを上から読んでみたけど、なんだかスゲー楽しそうじゃん? なんだか羨ましいよ。マジで。 あの頃、この2chのFORTRAN(超初心者用)スレがあったら・・・・。 なんて、思ってしまったけど、仮定法過去完了で人生を語るのはやめようと思う。 皆さんお元気で。 ひっそりと心の奥底で応援いたします。
204 名前:デフォルトの名無しさん [2006/02/26(日) 01:20:51 ] >>203 昨日の涙を今日の笑顔に変えて、でっかい夕日に向かって走るんだ! それはそうとFORTRANの教科書や教育課程はろくなものが無い。 面白くなくて訳分からなくなるのが標準だ。 やさしく分かりやすく書くということを、内容を整理して書くことではなく、 本文と無関係な下手糞な挿し絵をちりばめる事だと思っている世界だw
205 名前:デフォルトの名無しさん [2006/02/27(月) 00:55:37 ] さぁ宿題をもってきたまえ
206 名前:デフォルトの名無しさん mailto:sage [2006/02/27(月) 13:35:32 ] >>203 僕はFORTRANスレで助けてもらったおかげで 大学院を無事修了できました。 ここの住人の方々には本当に感謝しています。 僕もがんばって、知恵で人を助けられるような人間になりたい
207 名前:デフォルトの名無しさん mailto:sage [2006/02/27(月) 14:16:38 ] >>204 うむうむ 「作法」が執筆された時に 77 があったら良かったのに。 ratfor で見た目がちょっと違うというだけで、 初学者には敬遠されてしまうから。 これも仮定法過去完了だぬ。
208 名前:デフォルトの名無しさん [2006/02/27(月) 16:04:00 ] >>206 おめ! これからも山崎渉を・・じゃなかったFORTRANスレを応援してくださいw
209 名前:デフォルトの名無しさん mailto:sage [2006/02/28(火) 13:20:06 ] >>204 『FORTRAN 入門』浦昭二 が名著だと思う。 うちの大学ではどこでも転がっている標準本。 Fortran90 への対応を希望する。
210 名前:デフォルトの名無しさん [2006/02/28(火) 19:56:27 ] >>209 オレもそれのFORTRAN77版で習ったんだけどさ、 あれが名著と言われるようでは日本もお終いだと考えるべきだと思う罠www 前半例題で後半が文法という形式以外は例題もいまいちだしいいとこなしだと思うよ。
211 名前:デフォルトの名無しさん mailto:sage [2006/02/28(火) 20:08:01 ] 日本語で書かれたFortran90以降の機能が詳しく解説されてる本ってない? 近所で探してみたけど、どれも全くの入門書止まりだったり FORTRAN77に毛が生えたような本しか見つからなくて。
212 名前:デフォルトの名無しさん mailto:sage [2006/02/28(火) 20:38:07 ] >>211 これが結構いい。 コードも比較的Fortran90の機能だけで書こうとしている。 入門 Fortran90実践プログラミング SOFTBANK BOOKS 東田 幸樹 (著), 山本 芳人 (著), 熊沢 友信 (著) ttp://www.amazon.co.jp/exec/obidos/ASIN/4890524932/249-3009705-2437946 しかし絶版だったwwww
213 名前:デフォルトの名無しさん mailto:sage [2006/02/28(火) 21:19:16 ] >>210 そうかな? 文法事項を段階的にかつ網羅的に適用した、 適切な入門例題だと思うが。 科学技術計算を意識した例題が多いというのも、 FORTRAN という言語の性質上、好ましい。 >>211 そうだよな。 Fortran90 以降の名著が少ない(あっても絶版)というのは、 Fortran 市場を反映しているようで、残念でならない。 『FORTRAN 入門』浦昭二を90向けに改訂するなら、喜んで手伝うが。
214 名前:デフォルトの名無しさん mailto:sage [2006/02/28(火) 21:21:08 ] >>209-210 あの本はFORTRAN77版だけじゃないんですか? 詳細キボンヌ.("・ω・`)ノ
215 名前:デフォルトの名無しさん mailto:sage [2006/03/01(水) 03:02:46 ] >>214 あの本はFORTRAN66版がある。 アマゾンとかで検索してFORTRANというだけの77のついていないのがそれ。 それを元にFORTRAN77版を書いているので、 わりとすっきりしていたFORTRAN66版に比べるとFORTRN77版は いまいちな気がしないでもない。 FORTRAN90の教科書だったら、FとかLahey ELFのようにFORT77以前との 互換性を捨て去ったバージョンで書くのがすっきりしていいと思う。Fなんかは 色々入門書が出ていたと思う。もっとも肝心のFがNAGのフロントエンドを入れた せいで、当初の過去互換性を切り捨てた簡潔な言語になるという理想から 逸脱して迷走しているのがずっこける。 www.fortran.com/F/ www.fortran.com/ FORTRAN90で導入された新しい機能を用いれば、昔PASCALなんかで やっていた正則な構造化(モジュール化)されたプログラム書法が身につくと思うのだが、 いかんせん現実問題としてはFORTRAN77やFORTRAN66のプログラムをポンと渡されて、 動かせと言われたりするから、まあどうしたものか分からん。
216 名前:デフォルトの名無しさん [2006/03/02(木) 15:37:49 ] PROGRAM GGGG IMPLICIT NONE INTEGER*8 :: N,K,NH,M,I REAL*8 :: GANMA2(0:10000),GANMA3(0:10000),GANMA4(0:10000) REAL*8 :: BETA2,BETA3,BETA4,SECHYP,EAMP0,ER(0:2047),EI(0:2047) REAL*8 :: COS,SIN,ERK,EIK,T0,T,PI,FRQ,FQ,H,C,CD,CDD,WL,ROU,TAU0 COMPLEX*16 :: E(0:4094),EK M=11 N=2**M NH=N/2 PI=4.0D0*DATAN(DBLE(1.0D0)) T=5.12D-12 TAU0=0.22D-12 C=3.0D+8 CD=-42.0D-1 CDD=0.0D0 WL=1.55D-6 H=5.0D-5 BETA2=-CD*WL*WL/(2.0D0*PI*C) BETA3=WL*WL*WL*(WL*CDD+2.0D0*CD)/(4.0D0*PI*PI*C*C) BETA4=0.0D0 T0=TAU0/(2.0D0*DLOG(DSQRT(DBLE(2.0D0))+DBLE(1.0D0))) EAMP0=10.0D0
217 名前:デフォルトの名無しさん [2006/03/02(木) 15:41:26 ] DO K=0,N-1 SECHYP=DBLE(1.0D0)/DCOSH((T/T0)*(DBLE(K)/DBLE(N)-DBLE(0.5D0))) E(K)=CMPLX(EAMP0*SECHYP,0.0D0) END DO DO K=0,NH-1 ROU=DBLE(K)*T0/T FRQ=PI*ROU/T0 GANMA2(K)=-H*BETA2*PI*PI*ROU*ROU/(T0*T0) GANMA3(K)=-H*BETA3*PI*PI*PI*ROU*ROU*ROU/(T0*T0*T0)*2.0D0/3.0D0 GANMA4(K)=-H*BETA4*FRQ*FRQ*FRQ*FRQ*1.0D0/3.0D0 FQ=ROU/T0 END DO DO K=0,20,1 EK=E(K)*CEXP(CMPLX(0.0d0,(GANMA2(K)))) EK=EK*EXP(CMPLX(0.0d0,(GANMA3(K)))) EK=EK*CEXP(CMPLX(0.0d0,(GANMA4(K)))) E(K)=EK END DO END PROGRAM GGGG
218 名前:デフォルトの名無しさん [2006/03/02(木) 15:47:14 ] DO K=0,20,1 ERK=ER(K)*DCOS(GANMA2(K))-EI(K)*DSIN(GANMA2(K)) EIK=EI(K)*DCOS(GANMA2(K))+ER(K)*DSIN(GANMA2(K)) ERK=ERK*DCOS(GANMA3(K))-EIK*DSIN(GANMA3(K)) EIK=EIK*DCOS(GANMA3(K))+ERK*DSIN(GANMA3(K)) ERK=ERK*DCOS(GANMA4(K))-EIK*DSIN(GANMA4(K)) EIK=EIK*DCOS(GANMA4(K))+ERK*DSIN(GANMA4(K)) ER(K)=ERK EI(K)=EIK END DO END PROGRAM GGGG 連投すみません、216,217と計算が実数か複素数かだけの違いなのですが 217ではなぜか範囲を広げるほど虚数の値がかけ離れていきます 桁落ちでもないのですが、どなたか考えられる原因を教えてくださいm(__)m
219 名前:デフォルトの名無しさん [2006/03/03(金) 12:54:26 ] >>218 範囲を広げるという意味が良くわからんので、適当に書いてみるw EK=E(K)*CEXP(CMPLX(0.0d0,(GANMA2(K)))) EK=EK*EXP(CMPLX(0.0d0,(GANMA3(K)))) EK=EK*CEXP(CMPLX(0.0d0,(GANMA4(K)))) この式で、EK(K)は最後に掛けたほうがいい。なぜなら、それ以外の部分は 全部位相因子なので幾ら掛けても、絶対値は1になるはずの量だから。 まずはそこでチェックしてみたらどうか? つまり EK = EXP(CMPLX(0.0d0,(GANMA2(K)))) EK = EK * EXP(CMPLX(0.0d0,(GANMA3(K)))) EK = EK * EXP(CMPLX(0.0d0,(GANMA4(K)))) ここでABS(EK)=1.0d0のはず(誤差を抜かして) もう一つの式でも同様にして、その段階で虚部を比較すれば、 より限定的な情報が得られて問題解決に近づくだろう。 EK = EK(N) * EK (ここで後ろのEKはpahase_factorとかの変数名にしたほうがいいと思うが まぁ好みの問題だ) あとCEXPは総称名EXPに統一したほうがいいだろう。 精度の規定値が気になるなるが、KIND=8をつければ強制できるはず。
220 名前:デフォルトの名無しさん mailto:sage [2006/03/03(金) 13:52:48 ] > ERK=ERK*DCOS(GANMA3(K))-EIK*DSIN(GANMA3(K)) > EIK=EIK*DCOS(GANMA3(K))+ERK*DSIN(GANMA3(K)) とあるけど、一行目で、ERKを書き換えてしまってはダメじゃないの?
221 名前:デフォルトの名無しさん [2006/03/03(金) 15:40:33 ] >>220 実数、虚数にわけてる計算はあっているので、ただしいはずです・・・
222 名前:デフォルトの名無しさん [2006/03/03(金) 16:13:32 ] >>219 ありがとうございます、試してみます EK=EXP(CMPLX(0.0d0,(GANMA2(K)),8)) といった感じで精度をあわせてしまえばいいんですよね?
223 名前:デフォルトの名無しさん [2006/03/03(金) 18:07:37 ] >>221 いや、1行目でERKが書き換わっているので、正しいとは思えない。 その2行で1つの計算のはずだから、虚部を求める時に新しくなった実部を 使ってはいけない。 これで正しいとすると、二つが一致しないのは当然。 ただこれが正しいことはまずありえないと思う。
224 名前:デフォルトの名無しさん mailto:sage [2006/03/03(金) 18:11:08 ] >>221 いや、式はあってるんだけど、1行目でreal partを計算する際に、 元の変数のreal partを書き換えてしまっているのでは? 2行目の右辺に出てくるERKはもはや元の変数のreal partではないないと思うけれど。
225 名前:デフォルトの名無しさん mailto:sage [2006/03/03(金) 18:11:51 ] かぶったw
226 名前:デフォルトの名無しさん mailto:sage [2006/03/03(金) 18:15:59 ] 式があっているってのは、実部虚部への分け方はあっている、ってことね。 そのプログラムは変だと思うよ。
227 名前:デフォルトの名無しさん [2006/03/03(金) 22:14:06 ] >>223 ~226 気づかなかった;;;サンクスです。
228 名前:デフォルトの名無しさん [2006/03/07(火) 22:19:56 ] もりあげようぜ!w
229 名前:デフォルトの名無しさん mailto:sage [2006/03/07(火) 23:26:03 ] 盛り上げようにも大学が春休みで宿題がない予感。
230 名前:デフォルトの名無しさん mailto:sage [2006/03/10(金) 22:52:46 ] 欠測のある平均値の求め方を教えてください。 10行ごとの各列の(欠測を除外した)平均値と欠測数を求める問題です。 時間,A,B,C 1,23.5,23.2,22.7 2,24.5,25.2,22.1 3,25.4,24,27.5 4,26.4,,22.4 5,23.5,22.4, と2000行、続きます。
231 名前:デフォルトの名無しさん [2006/03/11(土) 00:02:09 ] >>230 適当なのでもっとうまい方法もあるやも知れぬ。参考までに。 INTEL FORTRAN Ver.9 PROGRAM vipp IMPLICIT NONE INTEGER :: i, j, k REAL :: x(10) i = 0 DO i = i + 1 x = 0.0 READ(9, '(i5, 10F15.5:)', ADVANCE = 'NO', EOR = 98,END = 99) k, (x(j), j = 1, 10) 98 PRINT *, j, ":", SUM(x(1:j)) / REAL(j) END DO 99 PRINT *, "EOF" STOP END PROGRAM vipp 実行結果 C:\Documents and Settings\All Users\Documents\FORTRAN\vip\Debug>vip 3 : 23.13333 3 : 23.93333 3 : 17.63341 3 : 16.26667 3 : 15.30000 EOF
232 名前:231 mailto:sage [2006/03/11(土) 00:09:25 ] >>230 ごめw 列ごとの平均かw 風呂から上がったらまた考えるw
233 名前:230 mailto:sage [2006/03/11(土) 00:25:20 ] >>232 トライ、ありがとうございます。 温度なので、23度あたりになるはずです。 5列分の平均ですが、 A 24.66 , B 23.7 , C 23.675 内部ファイルとLEN 関数をつかって、 うまくできないかとチャレンジ中です。
234 名前:デフォルトの名無しさん [2006/03/11(土) 00:28:05 ] くたばれFORTRAN
235 名前:デフォルトの名無しさん [2006/03/11(土) 00:51:46 ] がんばれFORTRAN
236 名前:231 mailto:sage [2006/03/11(土) 00:52:36 ] >>233 単純に思いつく方法は 1.手抜き方式、0.0が読み取られたときを欠損値とするというやり方 2.内部ファイルに読み込んで、INDEX関数で”,”を区切りとして切り取るやり方 汎用性からみると2かな? 第3の方法を求めて FORMAT文がF95で進化したので、空データの読み取りが検知できないか今調べているw
237 名前:230 mailto:sage [2006/03/11(土) 00:56:23 ] >>233 使用コンパイラ Compaq VFでは、 空白を欠測ではなく0と認識してしまったので、ダメでした。 文字列として読み込んで、^@ の処理を考えます。
238 名前:デフォルトの名無しさん mailto:sage [2006/03/11(土) 01:28:02 ] こんな感じッスかね? program hoge implicit none integer, parameter :: N = 10, NT = 2000 real, parameter :: NG = -1.0E10 real :: A(N), B(N), C(N), t, aa, ab, ac integer :: ka, kb, kc, i, j, ios character(len=80) :: tmp open(unit=11,file="huge.dat",status="OLD",blank="NULL") loop_j: do j = 1, NT/N A = NG; B = NG; C = NG loop_i: do i = 1, N read(unit=11,fmt="(A)",iostat=ios) tmp if (ios < 0) then ! エラー処理は省略... exit loop_j end if read(unit=tmp,fmt=*,iostat=ios) t, A(i), B(i), C(i) end do loop_i ka = count(A <= NG); aa = sum(A, mask=(A > NG)) / (N-ka) kb = count(B <= NG); ab = sum(B, mask=(B > NG)) / (N-kb) kc = count(C <= NG); ac = sum(C, mask=(C > NG)) / (N-kc) print *, "欠測 = ", ka, kb, kc print *, "平均 = ", aa, ab, ac end do loop_j close(11) end program hoge
239 名前:デフォルトの名無しさん mailto:ゲェェ [2006/03/11(土) 01:33:55 ] test
240 名前:230 mailto:sage [2006/03/11(土) 01:56:46 ] >>238 ありがとうございます! 無事に解決できました。 10個とも欠測の時間帯の平均値が NaN と表記されて、 いたれりつくせりです。 count(A <= NG) と mask=(A > NG) がミソですね。 0割になりそうでならないのが少し不思議です。
241 名前:231 [2006/03/11(土) 02:05:07 ] 出遅れたかwwwwwwwwwww PROGRAM vipp IMPLICIT NONE INTEGER :: i, j, k CHARACTER(LEN = 136) :: buff REAL :: a, x(10) = 0.0 INTEGER :: n(10) = 0 DO READ(9, '(a)', END = 99) buff k = INDEX(buff, ',') READ(buff(:k), '(i10)') j buff = buff(k + 1:) DO i = 1, 10 k = INDEX(buff, ',') IF (k == 0 .AND. LEN_TRIM(buff) == 0) EXIT ! end by "," IF (k /= 1) THEN ! k == 1 is missing data : ",," READ(buff, '(F15.0)') a x(i) = x(i) + a n(i) = n(i) + 1 END IF buff = buff(k + 1:) IF (k == 0) EXIT ! end of record END DO END DO 99 PRINT *, "EOF" PRINT *, n PRINT *, x / REAL(n) STOP END PROGRAM vipp >>241
242 名前:231 mailto:sage [2006/03/11(土) 02:06:24 ] C:\Documents and Settings\All Users\Documents\FORTRAN\vip\Debug>vip EOF 5 4 4 0 0 0 0 0 0 0 24.66000 23.70000 23.67500 NaN NaN NaN NaN NaN NaN NaN
243 名前:230 mailto:sage [2006/03/11(土) 02:26:44 ] >>241 わかりやすい注釈までいれていただいて、ありがとうございます。 k = INDEX(buff, ',') buff = buff(k + 1:) LEN_TRIM(buff) == 0 など、文字列処理の強力さはさすがですね。 配列手続といい、文字列処理といい、 f90 の強力さに、あらためて惚れなおしました。
244 名前:230 mailto:sage [2006/03/11(土) 02:38:50 ] >>241 今、調べなおしてみると、 LEN_TRIM 以外は、f77 の機能のようですね。 f77 の文字列処理の先見の明に驚いてしまいます。
245 名前:231 mailto:sage [2006/03/11(土) 02:39:14 ] >>243 場合わけはあまりエレガントでなかった。もう少し冗長でも分かりやすくすべきかも。 buff = buff(k + 1:) これで長さが足りない分に空白が入るかどうか確かめておいた。 ちゃんと空白が入っているようなので、ごみが尻のほうに残ることは無い。 文法書にもそう書いてあった気がするのだが、記憶がアイマイミー。
246 名前:230 mailto:sage [2006/03/11(土) 02:54:36 ] >>245 INDEX を用いた切り分けや、テクニカルな文字列処理の手本 を示していただいただけでも、感謝感激です。 本当にありがとうございました。
247 名前:231 mailto:sage [2006/03/11(土) 03:38:39 ] >>246 喜んでもらえてうれしいお(^ω^)ノシ >>238 も勉強になった。漏れは固定FORMATの愛好者なのでCVS形式はほとんど使ったこと無い。 自由書式の時にCVS形式の空データは読み飛ばすとは知らなかった。0が入ると思っていた。 F77はINDEX関数がとても便利だったが、TRIM関数が無かったせいで初心者時代に苦労した。 ある程度習熟してからは、不定長の文字引数で尻から先頭に向かって空白以外が出るまで 数える関数などを自分で用意できるようになったが、そこに到達するまではかなり時間がかかった。 内部ファイルの使い方も共同研究の外国人の書いたプログラムを読んでいて初めて知った。 それまでこんな便利なものがあるとはまったく知らなかったw 後になって改めて文法書を読むと、文字変数を入力装置にできるとはさりげなく書いてあるのだが、 それがとても便利なものだということはまず分からない。 この辺のノウハウを徒弟制度や口伝に頼っているFORTRAN界の未来は暗いなと思ったりしてw
248 名前:デフォルトの名無しさん [2006/03/11(土) 08:27:30 ] ところでFortranに分割コンパイルっていつ入るんですか?
249 名前:デフォルトの名無しさん mailto:sage [2006/03/11(土) 10:30:55 ] >>248 単純に複数のプログラム単位をコンパイル&リンク出来るという意味でなら FORTRAN IIで副プログラム呼び出しとBinary Symbolic Subroutine Loaderが 使えるようになった1958年から。 複数のプログラム単位のコンパイルを自動化出来るという意味でなら FORTRAN IIモニタの出来た1959年から。 近代的なモジュールの機能が使えるようになったという意味でなら Fortran 90の規格が出来た1991年から。 ということでよろしいかな?
250 名前:デフォルトの名無しさん [2006/03/12(日) 21:48:13 ] 非線形連立代数方程式をとくFORTRANのコードをC++に移植しています。 解の一部がどうしても両プログラムで一致せず、 丸一日かけて色々と試行錯誤したところ、Fortranでreal型を使っていたところ、 c++でdouble型にしてしまっていたことが原因でした。 このような場合、c++への移植の際にもfloat型を使うなどしてもとのコードと精度を合わせた方がよいのでしょうか。 なんとなくより大きな範囲を扱える変数型の方がよさそうな気がするのですが、 移植元が倍精度を使っていないので迷っています。 移植元のコードは1980年頃に書かれたもので、計算時間との兼ね合いから単精度を選択したと捉えたほうがよいでしょうか。 また、計算誤差の発生しないdecimal型があると知りました。 一般に数値計算をする場合はこのような型を使うのでしょうか。 精度が高い代わりに計算速度が遅いと聞きましたので、 一般にはどのような基準で使い分けて折り合いをつけていくのか興味があります。 すみませんが、どなたかご存知の方がいらっしゃいましたらお教えいただけますか。 よろしくお願いいたします。
251 名前:デフォルトの名無しさん [2006/03/12(日) 23:43:23 ] >>250 精度が出てるのを確かめられたならdouble型にすべし。 floatにする必要はないと思う。 C++の組み込み型にdecimalがあるとはきいたことないが、 だた10進数の内部表現ができるってだけで(0.1とかが正確に表せるのかな?) 数値計算自体に誤差が出ないわけではない。はず・・・たぶん
252 名前:デフォルトの名無しさん [2006/03/13(月) 11:13:40 ] ところでFORTRANにリアルタイムイベントハンドラはいつ入るんですか?
253 名前:デフォルトの名無しさん [2006/03/13(月) 13:47:57 ] >>250 1980年代のコードである場合、浮動小数点には今とは違う事情がある。 現在の浮動小数点はIEEEの形式にほぼ統一されているが、かつてはメーカーごとに 実数の内部形式は異なっていた。そのために、同じワード長でも仮数部により多くの ビットを割り当てているものもあれば、指数部により多くのビットを割り当てているもの もあって、機種によって有効桁の範囲が違っていた。 (IBMは仮数部に、CRAYは指数部により多くのビットを割り当てていた。 さらに言えば、NECのACOSのあるシリーズのように1ワード=36bitとか、 CDCのいくつかのシリーズのように1ワード56?bitとかでワード長自体が 違うものもあった。) というわけで、書かれた対象機種が分かれば必要精度に関するヒントになる。 ただ数値演算プロセッサが倍精度で作られている以上 基本的に倍精度にしておくのがよろしいと思う。 まぁSSEで高速化を優先するならまた話は別だが・・・
254 名前:250 [2006/03/13(月) 20:34:42 ] >>251 , 253 ありがとうございます。 頂いたアドバイスに従って とりあえず、倍精度で移植を進めてみようと思います。 >現在の浮動小数点はIEEEの形式にほぼ統一されているが、かつてはメーカーごとに >実数の内部形式は異なっていた。 そういえば、コンピュータの精度に応じてコメントアウトすべしというような注釈のついた関数がありました。 そういうことだったんですね。勉強になります。
255 名前:デフォルトの名無しさん [2006/03/14(火) 01:24:29 ] >>250 DECIMAL型について言えば、あれは商業用の機能で、数値計算的にはあまり 利益がないと思う。特に計算スピードはがくっと落ちるはずである。 専門ではないから正確ではないが、商業の世界では利息で生じた小数点以下の 端数をあるところで切り捨てる(または四捨五入?)する慣例がある。浮動小数 点では2進法を使っている関係で丸め誤差から小数点以下の端数の切り捨てで 10進法の時と微妙なズレが生じ、大量の金額に対して計算すると慣例とのズレ が無視できなくなる。これに対する対策がdecimal型すなわち10進型である。 一般的には、1桁ごとに10進法の数字を1個割り当てて計算するので極めて 計算効率が悪い。1桁につき最低4ビット必要。同じビット数で表される数の 範囲が狭くなってしまう。 (確か8087コプロにもBCD演算機能があったはずだが、固定小数点だったような 気がする。) 数値計算的には、倍精度、倍々精度という方向に行くことはあっても、 10進演算の方向に行くことは特殊な場合を除いてないと思う。 実際FORTRANで10進演算はできないが、利用者からの不満は聞かない。 一方COBOLやPL/Iなどでは10進演算が出来るようになっている。
256 名前:デフォルトの名無しさん [2006/03/14(火) 01:53:35 ] >>254 >そういえば、コンピュータの精度に応じてコメントアウトすべしというような >注釈のついた関数がありました。 昔は精度に関する機種依存性が結構あって移植の問題になっていた。 Fortran90で数値の精度に関する関数が大量に導入されたのは、 この辺でみんな苦労していたからだと思う。ただ90年代に入ってから IEEE形式に集約されて行ったので、ややありがたみが減った。 最近は0割りが発生しても強行突破して計算を続けてくれるので便利だと思う。 投機的実行の為にわざわざIF文で排除したはずの0割りを実行して糸冬了とか 脳の血管切れそうな事態が起きなくなった。 Fortran2003(一部はFortran95の拡張規格)でIEEE754に関する様々な関数が 導入されているので、将来はよりマニアックな要請に対応できるはずである。
257 名前:デフォルトの名無しさん [2006/03/17(金) 01:29:56 ] PROGRAM TEST IMPLICIT REAL*8 (A-H,O-Z) IMPLICIT INTEGER (I-N) * DIMENSION G(50) * WRITE(*,*)'個数(入力数+1)' READ(*,*)N * WRITE(*,*)'整数' DO 10 I = N, 0, -1 READ(*,*)G(I) 10 CONTINUE * DO 500 I = N, 0, -1 WRITE(*,*)I,G(I) 500 CONTINUE * DO 510 J = N, 0, -1 WRITE(*,*)J,G(J) 510 CONTINUE * END これ実行するとG(0)の値がちゃんと出力されないんですが、何故ですか? DO500とDO510で、出力が違う値で出てきてしまいます。 あまりにも簡単すぎる質問で申し訳ないですが、誰か教えてください。
258 名前:257 [2006/03/17(金) 01:31:55 ] frtで実行するとこんなのが出ます。 ↓ jwe0019i-u The program was terminated abnormally with Exception Code EXCEPTION_A CCESS_VIOLATION. error occurs at _MAIN__ line 19 loc 0040108c offset 0000008c _MAIN__ at loc 00401000 called from o.s. error summary (Fortran) error number error level error count jwe0019i u 1 total error count = 1
259 名前:デフォルトの名無しさん mailto:sage [2006/03/17(金) 01:55:44 ] >>257 配列の使い方を復習しましょう。 ttp://www.g.dendai.ac.jp/lecture/fortran/fort07.html
260 名前:257 [2006/03/17(金) 02:28:35 ] >>259 なるほど・・・初歩の初歩ですね。 とてもよくわかりました。 助かりました。ありがとう。
261 名前:デフォルトの名無しさん [2006/03/17(金) 02:29:05 ] >>257 数学科や計算機学科での自然な数は0から始まるのだが、 FORTRANの自然数は1から始まる古典的な自然数体系を取っている。 したがってG(50)と宣言したときはG(1)〜G(50)までの領域が取られており、 G(0)はout of rangeになる。 エラーメッセージにACCESS_VIOLATIONと出ているが、これはは大抵 配列のはみ出しと思っていい。 G(0)がどうしても使いたければG(0:50)という形で宣言すればいいが、 まあ素直に1から始まる配列になれたほうがいいだろう。 エラーメッセージから見る限り富士通のコンパイラを使っていると思うが、 デバッグ用のオプションに配列はみだしをチェックするサブスクリプトチェックの項目が あるだろうから、デバッグ段階ではそれをオンにしておけばはみだしが発生したとき そのソース行を教えてくれる。エラーが取れたら、チェックを外せばよい。
262 名前:259 mailto:sage [2006/03/17(金) 11:56:35 ] >>261 めちゃめちゃ親切に説明して頂いて助かります。 富士通のコンパイラまでわかるなんて、凄いです。 エラーメッセージの意味が理解できなかったので、まだまだでした…精進します。
263 名前:262 mailto:sage [2006/03/17(金) 11:58:40 ] 自分、257でした。 259さん、すみません。
264 名前:http://www.vector.co.jp/soft/win95/util/se072729.html mailto:http://www.microsoft.com/japan/windowsxp/64bit/default.mspx [2006/03/18(土) 19:33:30 ] 64bitに対応したトリップ検索プログラムありますか? TextSS のWindowsXP(Professional)64bit化おながいします もしくは64bitにネイティブ対応したテキスト置換ソフトありますか?
265 名前:デフォルトの名無しさん [2006/03/18(土) 23:10:21 ] この板でも爆撃喰らうんだな。VIPでは日常茶飯事だがw
266 名前:デフォルトの名無しさん [2006/03/26(日) 07:13:26 ] xxxx01.txt xxxx02.txt .... みたいな連番になっているファイルを順番に読み込むようにしたいのですが、 読み込むファイル名の部分をどのような書式にすれば良いのでしょうか? ((文字列+整数)をまとめて文字列として認識する方法が分かりません)
267 名前:デフォルトの名無しさん mailto:sage [2006/03/26(日) 11:30:18 ] >>266 内部ファイルを使うのが一番手っ取り早いだろう。 CHARACTER*10 FNAME INTEGER I DO I = 1, 20 WRITE(FNAME,'(A, I2.2, ''.txt'')') 'xxxx', I OPEN(10, FILE=FNAME, STATUS='OLD') : ファイルの読み込み : CLOSE(10) END DO
268 名前:266 [2006/03/26(日) 20:41:47 ] >>267 どうもありがとうございます。助かります。 申し訳ないですが、もうひとつ質問、 連番になっていなくても、ディレクトリにあるファイル全部を 読み込むような手段はあるでしょうか?
269 名前:デフォルトの名無しさん mailto:sage [2006/03/26(日) 23:22:58 ] >>268 Fortran95 までの標準仕様ではディレクトリの操作や検索は出来ない。 しかし、大抵の処理系にはファイル操作関係の拡張手続きが付いているので それらを使えば可能。 以下は Compaq Visual Fortran での例: use DFLIB implicit none character(len=100) :: dir, files, fname integer(kind=4) :: handle, fnlen type(FILE$INFO) :: info : dir = "D:\DataDir\" files = trim(dir) // "*.txt" handle = FILE$FIRST do fnlen = GETFILEINFOQQ(files, info, handle) if ((handle == FILE$LAST) .or. (handle == FILE$ERROR)) exit fname = trim(dir) // info%NAME open(unit=10, file=fname, status="OLD") : ファイルの読み込み : close(10) end do : 詳しくは処理系のマニュアル等を参照のこと。
270 名前:266 mailto:sage [2006/03/27(月) 20:27:30 ] >>269 どうもありがとうございました。 連番に直してから読み込むことにします。
271 名前:デフォルトの名無しさん mailto:sage [2006/04/05(水) 17:37:56 ] format 文について、教えてください。 配列Aのサイズ変化にあわせて、 format を可変にしたい場合どうすればよいのでしょうか? program main integer, parameter :: NUM=4 real*8 A(NUM) integer n do n=1,NUM A(n)=0.1*n end do ! write (6,'(1x, NUMf5.1)') (A(n),n=1,NUM) ! これはエラー write (6,'(1x, 4f5.1)') (A(n),n=1,NUM) ! これなら通る end
272 名前:デフォルトの名無しさん mailto:sage [2006/04/05(水) 18:08:54 ] write文で DO型並びを使わず愚直に DO文をかく。 write(6, '(1x, $)') do n=1, NUM write(6, '(f5.1, $)') A(n) end do write(6, '(/)') FMT記述子を文字列変数にするという手もあるが、 こちらの方がシンプル。
273 名前:271 mailto:sage [2006/04/05(水) 20:36:03 ] >>272 ありがとうございます。無事にできました。 改行制御編集記述子と斜線編集記述子を組み合わせれば、 できるのですね!
274 名前:デフォルトの名無しさん mailto:sage [2006/04/05(水) 20:58:19 ] 仕様上はFORMAT書式に対応する項目がなくなった時点で書式制御が終了するので 出力する項目に対して多めに指定してやっても良い(ちょっと強引だが) write(6, '(1X, 100F5.1)') (A(n),n=1,NUM) 処理系依存だが、<> でくくった中に整数式を書ける処理系もある。 write(6, '(1X, <NUM>F5.1)') (A(n),n=1,NUM) ついでに、コロン編集記述子を使えば入出力項目がなくなった時点で 以降の書式を無視して終了させられる。 write(6, '(1X, 100(F5.1, :, ", "))') (A(n),n=1,NUM)
275 名前:デフォルトの名無しさん [2006/04/05(水) 21:01:15 ] >>272 $ 指定子ってFortranの規格外でないかい?
276 名前:271 mailto:sage [2006/04/05(水) 21:13:08 ] >>274-275 情報、ありがとうございます。 過大定数の仮代入やコロン編集記述子は、アリですね! <> でくくった中に整数式を書ける処理系 Compaq Visual Fortran ではできました!すごい! 処理系依存はできるだけ避けたいと思っているので、 考えどころですね。 改行制御編集記述子は規格外でしたか! なかなか使い勝手のよさそうな機能なのに。
277 名前:デフォルトの名無しさん mailto:sage [2006/04/06(木) 10:53:52 ] $の代わりにこっちでどうかな? write(*,'(f5.1)',advance='no') A(n)
278 名前:271 mailto:sage [2006/04/06(木) 12:35:24 ] >>277 ありがとうございます。 こちらでもできました! 停留入出力という技もありましたね! F90 の書式仕様の理解は、手を抜いていましたが、 まじめに取り組むべきだと思いました。
279 名前:デフォルトの名無しさん [2006/04/07(金) 19:33:01 ] 教えてください!! 初めて書き込みさせていただきます。 Fortranのプログラムの課題が出ているのですがわからなくて・・・ 簡単な内容なんだと思うのですが、 みなさんのお力貸していただけないでしょうか?? 内容は 配列データa(i) (i=0,Num-1) が与えられたとき、 このデータの平均値および標準偏差を計算するプログラムを書け。 というものです。 お願いします!!
280 名前:デフォルトの名無しさん mailto:sage [2006/04/07(金) 20:31:05 ] >>279 平均値と標準偏差を求める式は知っているな? それをそのまま書けばよい。 avg = sum(a(0:Num-1)) / Num v = sum((avg - a(0:Num-1))**2) / Num s = sqrt(v)
281 名前:デフォルトの名無しさん [2006/04/08(土) 00:17:30 ] >>280 ありがとうございます!! 書いてみます!
282 名前:デフォルトの名無しさん [2006/04/08(土) 00:32:04 ] 学校の課題のこのプログラムが、全体として何が行われているか、どなたか教えてください! お願いします。 real::x,x1,x2,func real::dy,delt=1.e-6 read(*,*) x1,x2 if(func(x1)*func(x2) > 0.0) then write(*,*) 'boo boo' stop end if dy = sqrt(-func(x1)*func(x2)) do while (dy > delt) x=(x1+x2)/2.0 if(func(x1)*func(x) > 0.0) then x1=x else x2=x end if dy = sqrt(-func(x1)*func(x2)) end do x=x1 if(abs(func(x1)) > abs(func(x2))) x=x2 write(*,*) x end
283 名前:デフォルトの名無しさん mailto:sage [2006/04/08(土) 06:52:57 ] >>282 方程式の解、二分法 ttp://www.arch.kumamoto-u.ac.jp/hagane/yamanari/joho3/bisec.html
284 名前:デフォルトの名無しさん [2006/04/08(土) 11:14:08 ] >>283 ありがとうございます! URLとっても参考になりました。 これでやっとレポート書けそうです。 ありがとうございます!!
285 名前:デフォルトの名無しさん [2006/04/08(土) 13:27:05 ] しばらくぶりに・・・・・・宿題もっと持って来い!
286 名前:デフォルトの名無しさん [2006/04/12(水) 09:42:26 ] こんにちわ。 02.dat,05,dat,08,datなどのように、 飛び飛びで01.datから10.datまでの間の番号のついたファイルがあります。 ただし、どの番号のファイルがあって、どの番号が無いのかは 時々刻々と変わります。 このファイルを、01から、10まで、順番にOPENしてREADしたいのですが、 このとき、存在しない番号のファイルをスキップするにはどうしたらよいでしょうか。 status='old'を試しましたが存在しない番号のところで止まってしまいます。 ヒントだけでもよいのでよろしくお願いします。
287 名前:デフォルトの名無しさん [2006/04/12(水) 09:44:56 ] 追記 status無しのただのOPEN文だと、存在しない番号ファイルを 空ファイルで作ってしまいます。これを作らないようにしたいのです。
288 名前:デフォルトの名無しさん mailto:sage [2006/04/12(水) 12:29:36 ] >>286 logical :: exist character(len=80) :: filename do i=1,10 write(filename,'(i2.2,".dat")') i inquire(file=filename,exist=exist) if(exist) then open(io,file=filename,status='old') ! close(io) endif enddo
289 名前:デフォルトの名無しさん mailto:sage [2006/04/12(水) 16:26:44 ] 以下の複素多項式p(z)(zは複素変数)のゼロ点を全て、ニュートン法で求めよ。 (1)p(z)=z**2+4*i (2)p(z)=z**4-2*z**3+2*z**2-2*z+1 お願いします。
290 名前:デフォルトの名無しさん [2006/04/12(水) 22:51:27 ] PROGRAM newton IMPLICIT NONE INTEGER :: i, n REAL :: pi COMPLEX :: z pi = 4.0 * ATAN(1.0) n = 4 !2 DO i = 1, n z = EXP( 2.0 * pi * CMPLX(0.0, REAL(i) / REAL(n)) ) DO IF ( ABS(f(z))**2 < EPSILON(REAL(f(z)))**2 + EPSILON(IMAG(f(z)))**2 ) EXIT z = z - f(z) / df(z) END DO PRINT *, 'finished', z, f(z) END DO STOP CONTAINS COMPLEX FUNCTION f(z) IMPLICIT NONE COMPLEX, INTENT(IN) :: z f = z**4 - 2.0 * z**3 + 2.0 * z**2 - 2.0 * z + (1.0, 0.0) ! f = z**2 + (0.0, 4.0) RETURN END FUNCTION f !---------------------------------- COMPLEX FUNCTION df(z) IMPLICIT NONE COMPLEX, INTENT(IN) :: z df = 4.0 * z**3 - 6.0 * z**2 + 4.0 * z - (2.0, 0.0) ! df = 2.0 * z RETURN END FUNCTION df !---------------------------------- END PROGRAM newton
291 名前:デフォルトの名無しさん [2006/04/12(水) 23:03:46 ] 解 finished (-1.414214,1.414214) (0.0000000E+00,1.3691417E-07) finished (1.414214,-1.414214) (0.0000000E+00,1.3691417E-07) Press any key to continue finished (-7.1054274E-15,1.000000) (-2.8421709E-14,0.0000000E+00) finished (0.9998764,-2.0247151E-11) (0.0000000E+00,1.0012824E-14) finished (1.1924881E-08,-1.000000) (4.7699519E-08,0.0000000E+00) finished (1.000000,1.7484555E-07) (0.0000000E+00,5.6843419E-14) Press any key to continue ふつう、n次代数方程式の初期値は、1のn乗根から出発するのだが、 2番目の問題はそれがすでに解だったりして、newton法を使う前にLOOPから抜けてしまうw 問題設定が悪いw Newton法では微係数が必要なのだが、ここでは手動で微分して関数として与えた。 発展形としては数値微分するもよし、多項式なら機械微分するもよし。 収束判定条件にはEPSILON関数を使ってみた。 あまり真面目に考えてない。
292 名前:デフォルトの名無しさん mailto:sage [2006/04/13(木) 11:35:03 ] どうもありがとうございます。 学校でやってみます。
293 名前:デフォルトの名無しさん [2006/04/13(木) 13:56:30 ] >>288 様 ありがとうございます。 教えていただいたコードをそのままやってみたのですが、 existの中身がファイルのある無しに関わらず常に「F」になって if文の中に入っていきません。原因として何が考えられるでしょうか。 使っているコンパイラはFTN95というやつです。 INQUIREというヒントをいただきましたので、自分でも考えてみます。 ありがとうございました。
294 名前:293 [2006/04/13(木) 14:04:39 ] できました。 ファイルの拡張子指定ミスでした。 大変失礼いたしました。orz
295 名前:デフォルトの名無しさん [2006/04/21(金) 20:32:22 ] あげ
296 名前:デフォルトの名無しさん [2006/05/01(月) 13:36:24 ] そろそろ 宿題持ってこないか?w
297 名前:デフォルトの名無しさん [2006/05/04(木) 01:54:12 ] 質問です。 私のやりたいことは、 file_001.txt file_002.txt file_003.txt ・・・・ とナンバーの振られたファイルを順次読み込んでいくプログラムを作りたいのです。 do文などで何とかならないものでしょうか?
298 名前:デフォルトの名無しさん [2006/05/04(木) 02:08:36 ] >>297 character*12 fname ・・・ do i=1,20 write(fname, '(''file_'', I3.3, ''.txt'')') i open(unit=11, file=fname, status='OLD') ・・・ close(11) end do こんな感じでどうでしょう。
299 名前:297 [2006/05/04(木) 02:27:59 ] できました!ありがとうございます。 ここでwrite文はなにをしてるんでしょうか? fnameの定義ですか?
300 名前:デフォルトの名無しさん mailto:sage [2006/05/04(木) 09:36:38 ] >>299 内部ファイルを使って文字列変数 FNAME に 'file_' + 3桁の整数 + '.txt' を書き込んでいる。 つまり、ループカウンタ I に応じて ファイル名 'file_001.txt' 〜 'file_020.txt' を生成している。 内部ファイルについての詳細は↓やマニュアル等を参照のこと。 ttp://docs.sun.com/source/806-4843/Cp2_io.html