2016-12-09 5 views
0

と一致していない、摂氏機能タイプがIは、Fortranに新しいです関数定義

program Console1 

implicit none 
real, parameter :: ikind = selected_real_kind(p=15) 
real (kind = ikind):: c,f,o,faren 
print *, "enter a temperature in degrees celsius" 
read *, c 
write(*,10) "farenheit =", faren(c) 
10 format(a,f10.8) 

end program Console1 



function faren(c) 

real, parameter :: ikind = selected_real_kind(p=15) 
real (kind = ikind):: c,f 
faren = (9/5)*c + 32 

end function faren 

から華氏を返す関数でいくつかの練習のコードを書いて、私は、エラー#7977を取得:関数参照のタイプがありません関数定義の型と一致しません。

だから私が変更した場合function faren(c)からreal function faren(c) 私は同じエラーが発生しますが、タイプは同じですか?

私に何か不足していますか?メインプログラムで関数を定義する必要はありますか?

+3

'implicit none'を関数本体に追加すると、' real function faren'で部分的に取り上げるヒントが得られます。あなたのコンパイラは 'real'と' real(kind = ikind) 'が同じではないと言っています。定義は一貫しており、状況は良好です。 [明示的なインタフェースを利用できるようにすると、モジュールや内部関数についての情報が得られます。] – francescalus

答えて

2

がものはすでに述べた構造/コード配列に加えて、いくつかの問題があります:あなたは新しいですので

私は共有から多くのことを学んだ偉大なリソースを持っています。

まず、KINDはあなたが理想的

integer, parameter :: ikind = selected_real_kind(p=15) 

real, parameter :: ikind = selected_real_kind(p=15) 

を変更したいので、あなただけの1(つまり、モジュール内の)場所と参照してそれを定義する、整数でありますそれはあなたのメインプログラムと関数の両方からですが、コードはテストの目的と同じようにすべきです。

Fortran(およびPython2)の新入社員を頻繁に訪れる2番目の問題は、実数と整数は別個の型であり、一般的には互換性がないということです。

faren = (9/5)*c + 32 

整数除算は、整数結果を有するので

faren = (1)*c + 32 

に簡素化;より正確に

faren = (9.0/5.0) * c + 32.0 

あるいは、farenがで定義されている場合:9/5 = 1

Fortranは(それが言語の全体のポイントのようなものだ)ので、あなたはおそらく何をしたいです数値についてうるさいですikindの特定精度、

faren = (real(9.0,ikind)/real_(5.0,ikind)) * c + real(32.0,ikind) 

又は

faren = (9.0_ikind/5.0_ikind) * c + 32.0_ikind 

この構文は人の頭を爆発させる傾向があります。最新のFortranへようこそ)

最後の号はFortran I/Oの恐怖を扱っています。デザインの観点からは、ユーザーが期待する結果を知り、出力形式で表示できることを確認する必要があります。 cの正当な入力値の範囲は、コードのユースケースに依存するいくつかの上限に-273.15(与えても受け取ります)です。あなたが調理温度を扱っているなら、おそらく400.0を超えないでしょう。あなたが融合研究をしているならば、はるかに高くなる可能性があります。小数点以下8桁は有益か信憑性がありますか?この場合、コードをテストしているだけで、出力の精度はあまり必要ないかもしれません。あなたのような何かに出力形式を変更したいと思う:

10 format(a,es10.2) 

または

10 format(a,g16.8) 

あなたは(ドットの前に数)の合計フィールド幅を確保する必要が小数部を含むことができます(数字の整数部分と符号と指数を表示するのに必要なスペースを加えたものです。科学記法の場合、4文字は仮数記号、小数点、 'E'と指数記号で食べられます。 *の出力形式を使用することから始めるほうが安全かもしれません。数字やフォーマットと同時に戦うのはイライラします。

1

これはニュアンスをうまくやっていくための手間と簡単な始まりです。

個人的には、私は9/5ではなく数学のために実数を使用し、モジュールを使用します。この例では、C2Farenに実数または二重整数を渡すことができ、実数型または二重型のどちらを使用するかは、インターフェイス/プロシージャによって判断されます。次に、異なる精度が必要な場合に備えて、いくつかのオプションがあります。次に、あなたのプログラムが使用n個の第2ラインを介してモジュールを使用しています

MODULE MyTEMPS 
PRIVATE 
DOUBLE PRECISION, PARAMETER :: C2F_ScaleFact = 1.8D0 
DOUBLE PRECISION, PARAMETER :: F2C_ScaleFact = /(1.0D0/1.8D0)/ 
DOUBLE PRECISION, PARAMETER :: F2C_Offset = 32.0D0 
PUBLIC Faren2C 

INTERFACE C2Faren 
    MODULE PROCEDURE C2Faren_Real, C2Faren_DBL 
END INTERFACE 

CONTAINS 

!========= REAL VERISON ========= 
REAL FUNCTION C2Faren_Real(c) 
IMPLICIT NONE 
real, INTENT(IN ) :: c 

C2Faren_Real = (C*F2C_ScaleFact) + F2C_Offset 

RETURN 
END FUNCTION C2Faren_Real 

!========= DOUBLE VERSION ========= 
DOUBLE PRECISION FUNCTION C2Faren_DBL(c) 
IMPLICIT NONE 
DOUBLE PRECISION , INTENT(IN ) :: c 

C2Faren_DBL = (C*F2C_ScaleFact) + F2C_Offset 

RETURN 
END FUNCTION C2Faren_DBL 

!========= REAL VERSION (Faren to Centigrade) ========= 
REAL FUNCTION faren2C(Faren) 
IMPLICIT NONE 
REAL, INTENT(IN ) :: Faren 

faren2C = (faren - F2C_Offset)/F2C_ScaleFact 

RETURN 
END FUNCTION faren2C 

END MODULE MyTEMPS 

あなたが混在言語を行う場合にもISO_C_BINDINGを使用することができ

... ...

program Console1 
USE MyTEMPS   !<== Here 
implicit none 
real :: c, f 
DOUBLE PRECISION :: Dc, Df ! No way to get Df to C or DC in the module (yet)! 
print *, "enter a temperature in degrees celsius" 
read *, c 
write(*,10) "farenheit =", C2faren(c) 
10 format(a,f10.6) 

Dc = C 
write(*,12) "farenheit =", C2faren(Dc) 
12 format("DBL:",A,f10.6) 

F = Dc 
write(*,14) "Centigrade =", faren2C(F) 
14 format("DBL:",A,f10.6) 

end program Console1 

ので、/とモジュールの主な利点は、あなたがさまざまなプログラムでこのようなものを使いたいときに終わり、モジュールを一度テストして並べ替えることです...通常、この種のもの(モジュールがたくさんあります)をライブラリに入れます。モジュールには多くの機能があります。

実際のパラメータ:: ikind = selected_real_kind(p = 15)をモジュールに入れて、プログラムと関数の両方で使用することもできます。あなたは本当に近いですし、それは主にスタイルと実用性の問題です。

インテルFortranの場合は、REAL(KIND = 4)とREAL(KIND = 8)を使用できます。これはgfortranに移植できないため、ISO_C_BINDINGを使用する方が良いでしょう。 REALとDOUBLE PRECISIONを使用してください。

+1

*おそらくISO_C_BINDING *を使用する方が良いでしょう。組み込みモジュール 'iso_fortran_env'と' real64'や 'int32'のようなそれに含まれる種類の型を初心者にアドバイスする方が良いかもしれません。 –

+0

良い点@HighPerformanceMark私はgfortranのコンパイルを可能にするために多くのifortコードを変更する必要があるので、私にも良いリマインダです。 – Holmz

1

モジュールは素晴らしいですが、非常に単純なコードをお持ちの場合は、メインプログラムにサブルーチンと関数を配置する別の方法があります。あなたのパラメータを再宣言する必要はありません、あなたが取得する可能性があるので、機能はメインプログラムの内容に見ることができます。このように

program xxx 
stuff 

contains 

subroutine yyy 
function zzz 

end program xxx 

:トリックは、単語が含まれた後にそれらを置くことですより意味のあるエラーメッセージ。 http://www.uv.es/dogarcar/man/IntrFortran90.pdf

関連する問題