fortranの配列宣言について質問です。
下記の様に配列の変数をサブルーチンの内外で宣言することで違いが出てきました。
こういうものなのでしょうか。失礼します。


parameter(ine=4999)
c
call test1(ine) !error
call test2() !OK

stop
end

subroutine test1(ine)
dimension ary1(ine,50)

return
end

subroutine test2()
parameter(ine=4999)
dimension ary1(ine,50)

return
end

このQ&Aに関連する最新のQ&A

配列 FORTRAN」に関するQ&A: fortran 配列実行結果

A 回答 (4件)

着目すべき点は、おそらく二点。



1.もともとFortranは、サブルーチン・関数の引数は参照渡しが基本だそうです。その場合、定数を渡すことができるのか?

 参照渡しというのは、誤解を恐れずに言うと、変数のアドレスを渡すこと。定数には通常アドレスはありません。強いて言うと(これが問題ですが)、変数の場合は変数のセグメントにあるアドレスが渡されますが、定数の場合コードセグメントのアドレスが渡される可能性があります。一般的にはこれは実行時エラーを引き起こします。親切な処理系なら、コンパイル時にエラーで蹴られます。

2.もし、それを受け取ることができたとしたら、次の難関は、配列宣言のサイズを変数で動的に指定できるのか?

 明示的にメモリを確保するアロケート系の処理以外では、通常名前をつけて宣言する変数は、コンパイル時に大きさが決定している必要があります。test1版の配列宣言は、一つ目の引数が、サブルーチンの引数として宣言された変数になっています。
これは実行時まで内容が決まりません。

以上、通りすがりの者Fortranはやったこと無い者ですが、気になった点です。
    • good
    • 0
この回答へのお礼

詳しい解説ありがとうございました。
「つまり、大きさが決まっていない配列を無理やり宣言したため。」ということでしょうか。

エラーの無い方法でコードを書こうと思います。
ありがとうございました。

お礼日時:2011/04/12 20:41

call test1(ine)でエラーとなり、call test2() でエラーにならない理由はおそらく以下の通りです。



まずtest1内の配列ary1は引数としてわたってくるineの大きさに基づくものですので
可変サイズ(実行時までサイズが不明な)配列という扱いになります。
一方でtest2内の配列ary1は固定サイズ(コンパイル時にサイズが既知な)配列
という扱いになり、この違いがtest1ではスタックオーバーフローを引き起こし
test2ではエラーにならないことの理由かと思います。

test1は外部サブルーチンであり引数ineに何が渡って来ても正しく動作する必要があります。
(つまり実行時までtest1内のary1の大きさを決定することができません)
ですのでtest1内のary1の領域は実行時にスタック上に確保されることになりますが
おそらく、ご利用の環境においてのスタックサイズが十分に大きくない事により
スタックオーバーフローが発生しているのではないかと推測されます。

test2ではなぜエラーにならないかという点ですが、test2内において
ary1の大きさ(50x4999)は(実行時まで待つことなく)
コンパイル時に既に決定しています。そのためご利用のコンパイラでは
test2のary1の領域を静的に(スタック上にではないところに)用意しています。
これによりtest2ではスタックサイズに関係なくary1の領域が確保され、よって
エラーが発生しないという事になっているのかと思います。

以上ご参考になれば幸いです。
    • good
    • 0
この回答へのお礼

詳しい解説ありがとうございました。
「つまり、大きさが決まっていない配列を無理やり宣言したため。」ということでしょうか。

エラーの無い方法でコードを書こうと思います。
ありがとうございました。

お礼日時:2011/04/12 20:41

あぁそうだ,


・その「エラー」とやらがいつ出るのか (コンパイル時・実行時・その他 (できるだけ詳しく))
・(あるなら) エラーメッセージを「一字一句そのまま」
も情報としてあるべきでしょう.
    • good
    • 0

処理系は?


その処理系が従っている規格は?
その規格をじっくり読んで, それでも理解できなかったってこと?

この回答への補足

2003年に購入したintelのfortranです。

以前からこういう症状があったのかもう一度確認してみます。

補足日時:2011/04/12 00:07
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QFortran でのマイナス乗数の書き方

Fortranで、マイナスの乗数の書き方についてお尋ねします。

cosθのマイナス1乗をプログラムで表したいのですが、どのように書けばいいでしょうか。

実際に行いたい計算は、経緯度の2点間の距離で、下記のように記述してみましたが
行最後の**-1でエラーがでています。

Fortran記述式
2点間距離 = r*(cos(sin(y1)*sin(y2)+cos(y1)*cos(y2)*cos(x1-x2)))**-1)

計算したい式
2点間距離 = rcos^-1(siny1siny2+cosy1cosy2cos(x1-x2))

Fortran v4.1.2(g95 0.93)を使用しています。

初歩的なこととは存じますが、よろしくお願いいたします。

Aベストアンサー

「-1乗」って要するに逆数のことだから, 本当に「cosθのマイナス1乗」を計算したいなら
1/cos(なんちゃら)
で計算できる.

とはいえ cos^-1 θ って「cos θ の -1乗」じゃないんだけどね.

Qfortran 配列宣言

以下のプログラムの中でeth(n), eph(n)は、配列なのですが、配列宣言はどのようにしたらよいのでしょうか?doループでnが決まるのでどのように配列宣言したらよいかわかりません。いろいろと試してはみたのですがコンパイルの際エラーがでてしまいます。わかる方がいらっしゃったら教えて下さい。よろしくお願いします。
subroutine far_output
use consts
use fdtd
implicit none

integer :: n, i, td
real(8) :: s
real(8) :: theta, phi
real(8) :: sx, sy, sz, px, py
real(8) :: wth, wph, uth, uph
real(8) :: eth(1000), eph(1000)

open(10,file="far_field.dat")

! s = pi/180.0d0
phi = 0.0d0
! do i = 0, 180
! td = i
! theta = s*td
theta = pi/3.0d0
sx = cos(theta)*cos(phi)
sy = cos(theta)*sin(phi)
sz = -sin(theta)
px = -sin(phi)
py = cos(phi)
do n = 1, ntime
wth = wx(l,n)*dx+wy(l,n)*sy+wz(l,n)*sz
wph = wx(l,n)*px+wy(l,n)*py
uth = ux(l,n)*sx+uy(l,n)*sy+uz(l,n)*sz
uph = ux(l,n)*px+uy(l,n)*py
eth(n) = -z0*wth-uph
eph(n) = -z0*wph+uth

write(10,*) eth, eph
enddo
! enddo

close(10)

return
end subroutine

以下のプログラムの中でeth(n), eph(n)は、配列なのですが、配列宣言はどのようにしたらよいのでしょうか?doループでnが決まるのでどのように配列宣言したらよいかわかりません。いろいろと試してはみたのですがコンパイルの際エラーがでてしまいます。わかる方がいらっしゃったら教えて下さい。よろしくお願いします。
subroutine far_output
use consts
use fdtd
implicit none

integer :: n, i, td
real(8) :: s
real(8) :: theta, phi
real(8) :: sx, sy, sz, px, py
real(8) :: ...続きを読む

Aベストアンサー

「doループでnが決まる」ってどういう意味? 普通に考えると「何らかの do ループを実行した結果, 最終的に n が求まる」ということになりそうだけど, このプログラムでは「n をループ変数にした do構文」があるだけだよね. それを「doループでnが決まる」と呼ぶのはおかしいです.
しかもその do ループでは n が 1 から ntime まで動いているだけなので, 「n」なんか無視して ntime を使って配列を定義すればいい.
本当に動的にメモリを確保したいなら allocate を使うんだけど, 少なくともこのプログラムを見た限り allocate が必要であるとは思えないなぁ.

Qfortranで積分範囲を求める。

今、S=∮3/4(1+cos^2(x))dx [0,theta]という式があります。

Sはわかっていて、求めたいのは、積分範囲のthetaです。

fortranで台形を使った積分式を求める式はわかるのですが、
その場合だと、積分区間がわかっていて、微小にわけて計算するので、
今回のように、積分区間のthetaを求める方法がわかりません。

どなたか、わかる方がいらっしゃったらご指導お願いします。

Aベストアンサー

基本的には「theta を求めるために方程式を解く」ことになります.

この問題に関しては「不定積分しろ」ですが.

Qfortran allocateを使って配列宣言を

今変数 aについて考えています.aは i,jの2次元の座標におけるデータです.
a(1,1)は10個配列を持ちたい
a(1,2)は5配列を持ちたい
a(i,j)はn個配列を持ちたい
このような場合どのように配列を定義すれば良いのでしょうか?

例えば 2次元の大きさが3x3の場合で,それぞれの位置に配列したいデータ個数をnとします.
nには既に個数が定義されているとします.このとき aの配列は nを使ってどのように定義すれば良いのでしょうか?

integer n(3,3)
integer i,j
real, allocatable :: a(:,:,:)

do j=1,3
do i=1,3
n(i,j)=i*j
end do
end do

do j=1,3
do i=1,3
allocate (a(n(i,j),3,3))
end do
end do

では aの宣言が重複するためエラーになってします.

何方か良い方法を教えて下さい.

Aベストアンサー

> b=a(1,1,1)と書けるのでしょうか?

まあ,そんなことはないということは変数の宣言の仕方からわかるだろう。
以下に使い方の例を示す。

!まずは追加の宣言
real :: b(1), c(4), d

!そしてこんな感じ
!代入
do j=1,nn
do i=1,nn
do k=1,n(i,j)
ppa%pa(i,j)%a(k)=100*i+10*j+k
end do
end do
end do
!表示
!配列全部なら
b=ppa%pa(1,1)%a
print*,b
!配列の一部だけでも
ppa%pa(2,2)%a(3)=999
c=ppa%pa(2,2)%a
print*,c
!逆方向の代入も
d=ppa%pa(3,3)%a(5)
print*,d

QFORTRAN

初めまして。

今大学でFORTRANについて議論が交わされてるのですが
FORTRANについて知ってるいる方がいたら是非教えてください。

今のところ求めている情報としては
1.FORTRANの強み
2.FORTRANの弱み
3.FORTRANのこれから
4.FORTRANが抱えている問題

URLなどでも結構ですので是非情報をお持ちでしたら教えてください。

Aベストアンサー

Fortranの強みはベクトル化、パラレル化に向いていることです。ですからベクトルユニットを持ったコンピュータ、具体的にはスーパーコンピュータなどのプログラミングには適しています。
Fortranがなぜベクトル化パラレル化に強いかというとC言語のように構造化プログラミングや再帰呼び出しなどを通常はCほどは使わないのでコンパイラが理解しやすいのです。
以前ミニスーパーコンピュータを使っていたときもCよりもForTtranの方がベクトル化率、パラレル化率が高くその分高速で計算を行えました。
最近ではコンパイラの性能も上がってCなどでもベクトル化が進むようにはなりましたがやはりFortranの方が強いですね。

弱みとしては逆に構造化や再帰呼び出しなどの複雑なことが難しいので計算などの問題には強くてもシミュレーションの部分では少し弱くしかもコンパイル後のアプリケーションの大きさが大きめになることです。

Fortranのこれからですがスーパーコンピュータ南アkを使って高速な計算を行う分野ではまだまだ使われるでしょうが使用率でいったら少なくなっていくと思います。

Fortranの強みはベクトル化、パラレル化に向いていることです。ですからベクトルユニットを持ったコンピュータ、具体的にはスーパーコンピュータなどのプログラミングには適しています。
Fortranがなぜベクトル化パラレル化に強いかというとC言語のように構造化プログラミングや再帰呼び出しなどを通常はCほどは使わないのでコンパイラが理解しやすいのです。
以前ミニスーパーコンピュータを使っていたときもCよりもForTtranの方がベクトル化率、パラレル化率が高くその分高速で計算を行えました。
最近で...続きを読む

QFortranの変数の宣言のしかた

本によってばらばらなのですが、

1.  real(8) a,b,c
2.  real(8) :: a,b,c
3.  real a,b,c
4.  real :: a,b,c

これはすべて正しいとは思いますが、::の有無は何か意味があるのでしょうか。

Aベストアンサー

:: を挟んだ形式は Fortran90 で導入された記法です。FORTRAN77 までのような単純な宣言の場合はあってもなくても構わないのですが、Fortran90 で導入されたような様々な修飾子がついたり、下の回答にあるような初期値代入がある場合は必須になります。

例 F77 では型宣言と PARAMETER 文、DIMENSION 文を別々に行わなければなかったが、F90 では1行にまとめられる。
integer, parameter :: k = 10
integer, dimension(6) :: j


この他、Fortran2003 などで導入された無制限ポインタ(万能ポインタ、型無しポインタ)の割り付け時や、空要素配列構成子、forall 文のループ変数の型指定など、様々な状況下で使用されます。


任意の型がとれる unlimited pointer の scalar 変数宣言
class(*), allocatable :: p
allocate(integer::p)

[integer::] !要素数 0 の integer 型の配列

forall (integer(8):: i = 1:10**10) ! 32bit 整数の範囲を超えるループ変数

:: 省略形は、基本的に過去との互換性のために残してある記法で、新しくプログラムを書く場合は常に :: を付ける方が好ましいかと思います。

:: を挟んだ形式は Fortran90 で導入された記法です。FORTRAN77 までのような単純な宣言の場合はあってもなくても構わないのですが、Fortran90 で導入されたような様々な修飾子がついたり、下の回答にあるような初期値代入がある場合は必須になります。

例 F77 では型宣言と PARAMETER 文、DIMENSION 文を別々に行わなければなかったが、F90 では1行にまとめられる。
integer, parameter :: k = 10
integer, dimension(6) :: j


この他、Fortran2003 などで導入された無制限ポインタ(万能ポインタ、...続きを読む

QFortranプログラムからC言語で実装された関数を呼ぶ方法

Windows Vista Home PremiumにFTN95をインストールしたPCにて、Fortranのプログラミングをし始め、「Cpad for Salford FTN77」を利用してプログラミングをしています(FORTRAN77・Fortran90ともに)。FTN95でのFortranプログラミングに際し、FortranプログラムからC言語で実装された関数を呼ぶには、どのように対処すれば可能になりますでしょうか?何分初心者ですので、拙い質問かと思いますが、何卒ご教示願います。

Aベストアンサー

回答いたします。

ユーザーガイドの213ページ(アクロバットだと、231ページ)に出ています。具体的には、Fortranプログラム中に、C_EXTERNALという宣言をした関数は、Cの関数と同じくアクセスできるようになります。

そしてC側では、
#extern <返り値>関数名(引数)を与えれば、Cの関数として呼び込むことが出来ます。

ユーザガイドの仕様にしたがってサンプルを書いてみると。
サンプル2を例に取ります。

Fortran側
C_EXTERNAL WRITE 'WriteFile' : INTEGER*4
INTERGER*4 RESULT
RESULT=WRITE()
以下続く
最後は、RETURN

C側
#extern int Writefile(int);

こんな感じですね。

では。

QFortranの配列の大きさを変数にできるか。

Fortranで2次元の配列をつくろうと考えています。この配列の大きさを宣言する際に、大きさを変数にすることはできますか?

つまり、あらかじめ、nという文字に数字をあてはめておき、そのあとに
integer,dimension(n,n)::A
などという風に記述できるかという質問です。具体的には

program test16
implicit none
integer :: n
n=3
integer,dimension(n,n)::A
end program

という風にしたいのですが・・・。

Aベストアンサー

n を parameter にするとか, A を allocatable にして適当なタイミングで allocate するとか.

QMS-FortranとFortran90

私は研究でFortran90を使っているのですが、研究に使うプログラムはMS-Fortranを用いて書かれているものでした。

そこで質問なんですが、MS-FortranとFortran90の違いについて知っている方がいれば教えてください。
また、MS-FortranでかかれたソースコードをFortranにコピーした時に何か弊害はあるのでしょうか?(人づてに弊害が起こると聞いたことがあるのですが・・・)。

プログラミングを本格的に始めて、まだ3ヶ月ほどで用語の使い方がわかりにくいところがあるかもしれませんがよろしくお願いします。

Aベストアンサー

MicrosoftがFortranを出していた時期を考えると、多分ですが、Fortran77だと思いますね。
Fortran90自体、製品が揃ったのは90年からかなり立っています。そのころには、Microsoftの言語製品はCとBASICだけになっていたんじゃないかな。

なお、MS-Fortranに限らず、intel系のFortranでは、86系のアーキテクチャの影響でホストに比べ、一部の機能が制限されている場合があります、これらについてはマニュアルを参照してください。

Qfortran 配列実行結果

以下のように実行結果のプログラムを書いたのですが、実行結果の値の(配列)の内容がどのようになっているのか混乱しています。実行結果の値は、
n = 1, l = 1, 2, 3,...,180, n = 2, l = 1, 2, 3, .....180 ...... n = ntime, l = 1, 2, 3, ...180 と書き出されているのでしょうか?どなたかわかる方がいらっしゃったら教えて下さい。よろしくお願いします。

subroutine far_output
use consts
use fdtd
implicit none

integer :: n, i, td
real(8) :: s
real(8) :: theta, phi
real(8) :: sx, sy, sz, px, py
real(8) :: wth, wph, uth, uph
real(8) :: eth(1000), eph(1000)

open(10,file="far_field_eth.dat")
open(20,file="far_field_eph.dat")
open(30,file="far_field.dat")
! s = pi/180.0d0
theta = 0.0d0
! do i = 0, 360
! td = i
! phi = s*td
phi = 0.0d0
sx = cos(theta)*cos(phi)
sy = cos(theta)*sin(phi)
sz = -sin(theta)
px = -sin(phi)
py = cos(phi)
do n = 1, ntime
! s = pi/180.0d0
! theta = 0.0d0
! do i = 0, 360
! td = i
! phi = s*td
wth = wx(l,n)*dx+wy(l,n)*sy+wz(l,n)*sz
wph = wx(l,n)*px+wy(l,n)*py
uth = ux(l,n)*sx+uy(l,n)*sy+uz(l,n)*sz
uph = ux(l,n)*px+uy(l,n)*py
eth(n) = -z0*wth-uph
eph(n) = -z0*wph+uth

write(10,*) eth
write(20,*) eph
write(30,*) wx(l,n)

enddo
! enddo

l(エル)は前の(別の)プログラムで l = 1, 180 のdoループで計算させています。

以下のように実行結果のプログラムを書いたのですが、実行結果の値の(配列)の内容がどのようになっているのか混乱しています。実行結果の値は、
n = 1, l = 1, 2, 3,...,180, n = 2, l = 1, 2, 3, .....180 ...... n = ntime, l = 1, 2, 3, ...180 と書き出されているのでしょうか?どなたかわかる方がいらっしゃったら教えて下さい。よろしくお願いします。

subroutine far_output
use consts
use fdtd
implicit none

integer :: n, i, td
real(8) :: s
real(8) :: theta, phi
re...続きを読む

Aベストアンサー

補足に書いてあることの意味が分かりません.
「上4つの式は2次元配列なのに、最後の式2つは1次元配列になっている」と書かれていますが, 式が 1次元配列であるとか 2次元配列であるというのをどのような意味で使っているのですか? 式 (の右辺) で得られる値はスカラですし, それを代入しているのもスカラですよね.


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング