フォートランで作られたデータを、perlで作り直そうと始めました。
なんとか、perlの中で値の計算までは出来たのですが、
下記データの2フィールド目に対して積算の仕方が解りません。
awkでは、awk '{SUM += $2;printf("%s %10.4e\n", $1, SUM)}'でできましたが、
perlで中ではどのようにするのか?
1998-04-20T16:16:00 6.533078e+05
1998-05-01T01:59:00 1.501809e+06
1998-05-05T07:20:00 7.202719e+05
1998-05-05T07:24:00 9.799618e+05
ついでに、御存じでしたら、御教授ください。
awkとperlの計算結果は全く同じにでましたが、フォートランの結果は
下記のように微妙に違ってしまう処がございます。
それは、どうしてでしょうか?
awk,perl の結果 フォートランの結果 フォートランの7ケタの結果
7.202719e+05 7.202718e+05 7.2027181e+05
9.799618e+05 9.799616e+05 9.7996169e+05
以上 よろしくお願い致します。
No.3ベストアンサー
- 回答日時:
#2補足について。
この内容だと、Fortranでは単精度で処理されています。
参照: http://www.nag-j.co.jp/fortran/FI_17.html#AUTOTO …
実装にもよりますが、Cで言えば、float相当です。
http://ja.wikipedia.org/wiki/%E5%8D%98%E7%B2%BE% …
にあるように、有効桁は、10進で7桁程度です。
Perlの内部ではCで言えば、double相当の精度で計算しています。
http://ja.wikipedia.org/wiki/%E5%80%8D%E7%B2%BE% …
にあるように、有効桁は、10進で15桁程度です。
違いが出ているのは、7桁目です。
これは、単精度にとっては精度ぎりぎりの桁なので、誤差が出る箇所です。
対し、倍精度にとっては、まだ余裕のある桁です。
この差が、集計結果の違いに出ているのだと思われます。
この回答への補足
詳細な説明有難うございました。
より良い知識を得る事が出来き、フォートランとperlの違いが少し解りました。
安心してperlへ切り替えたいと思います。
では、御存じでしたら、示しましたデータについて、2フィールド目の指数表示のデータについて、perlで積算データを出力させるスクリプトを、ご教授して頂けると大変助かります。
宜しくお願い致します。
FortranとPerlの計算結果の精度についての、詳しい説明
ありがとうございました。なんとか、自力でperlで積算を求めるスクリプトを書く事ができました。
有難うございました。
No.4
- 回答日時:
既に答えは書かれています. 全ての回答を見てください.
この回答への補足
osamuyさんにご教授頂いていたのですが、コマンドプロンプトの画面の図が、私のPC上では、昨日チラッと見えただけて、見えなくなってしまいました。
確か、1ライナーで書かれていたとおもいます。
出来れば、perlのスクリプトの中で while文を使い入力データを1行ずつ呼び出しては、積算させて、出力ファイルへ書かせたいのです。
説明不足も申し訳有りません。
No.2
- 回答日時:
Fortranでは、どの型を使っていますか?
Perlでは、内部で倍精度実数相当の計算をしています。
Fortranで単精度を使っているなら、精度の違いが出ます。
この回答への補足
フォートランスクリプトの中身を下記に記述しました。
お恥ずかしい事に、私にはさっぱりわかりません。
ene=でエネルギーの計算をして
enecum=でエネルギーの積算を作っているようです。
open(11,file='lfall.dat')
open(12,file='enecum.dat')
open(13,file='eneind.dat')
read (11,'(2(1x,i4,4i2),2x,a3)') iyrf1,monf1,idyf1,ihrf1,
& minf1,iyrf2,monf2,idyf2,ihrf2,minf2,stnm ! period,station
read (11,'(2(1x,i4,4i2))') iyrd1,mond1,idyd1,ihrd1,
& mind1,iyrd2,mond2,idyd2,ihrd2,mind2 ! data
read (11,'(1x,3i6)') iymax,itickdy ! Ymax,Ytick-int
read (11,'(1x,3i6)') iamaxmm,iamaxnmps,idur ! legend Amax, dt
write(*,'(2(1x,i4,4i2))') iyrf1,monf1,idyf1,ihrf1,minf1,
& iyrf2,monf2,idyf2,ihrf2,minf2
write(*,'(2(1x,i4,4i2))') iyrd1,mond1,idyd1,ihrd1,mind1,
& iyrd2,mond2,idyd2,ihrd2,mind2
write(*,'(1x,2i6)') iymax,itickdy
write(*,'(1x,3i6)') iamaxmm,iamaxnmps,idur ! iamaxmm is fix
read(11,'(1x)')
c
enecum=0.0
pi=3.1415
rho=2600.0
c=3500.0
r0=20000.0
r02=r0**2
fact=0.00000001
fk=0.5
c
1 continue
read(11,1102) IY00,IM00,ID00,IH100,IMI100,IH200,IMI200,
1 LDMIN, ampx
1102 format(1x,i4,2i2,1x,2i2,1x,2i2,i5,f7.1)
if(IY00 .gt. 2020 .or. IY00 .lt. 1) go to 9000
ampxm=0.5*ampx*fact
ene=2.0*fk*pi*60.0*float(LDMIN)*rho*c*r02*ampxm**2
write(13,1210) oy,ene
enecum=enecum+ene
call time1(IY00,IM00,ID00,IH100,IMI100,oy)
write(12,1200) oy,enecum
write(*,1202) oy,enecum,ampx,ampxm,ene
1200 format(f10.4,3x,e12.5)
1210 format(f10.4,3X,e15.8)
1202 format(f10.4,3x,4e12.5)
go to 1
9000 continue
stop
end
subroutine time1(iy,im,id,ih,imin,oy)
dimension imday(12)
imday(1)=0
imday(2)=31
imday(3)=59
imday(4)=90
imday(5)=120
imday(6)=151
imday(7)=181
imday(8)=212
imday(9)=243
imday(10)=273
imday(11)=304
imday(12)=334
c
f4=0.0
m4y=mod(iy,4)
if(m4y .eq. 0) then
f4=1.0
if(iy .eq. 2000) f4=0.0
if(im .gt.2) f40=f4
endif
if40=f40
fd=(float(ih)+float(imin)/60.0)/24.0
fd=fd+float(id)
fm=float(imday(im)+if40)+fd
fm=fm/(365.0+f4)
oy=float(iy)+fm
return
end
FortranとPerlの計算結果の精度についての、詳しい説明
ありがとうございました。なんとか、自力でperlで積算を求めるスクリプトを書く事ができました。
有難うございました。
No.1
- 回答日時:
一例。
>awkとperlの計算結果は全く同じにでましたが、フォートランの結果は下記のように微妙に違ってしまう処がございます。
いわば環境依存です。
awkやperlは、OS標準ライブラリを使ってデータを読み込んだり、値を処理しているので。
計算誤差とかは別途検討する必要があります。
この回答への補足
#! /usr/bin/perl
open ( InFile, "< /home/tanaka/lfall.dat");
open ( OutFile, "> /home/tanaka/ene-perl.dat" );
open ( OutFileseki, "> /home/tanaka/lfall.dat.out" );
while ( <InFile> )
{
chop;
s/ +/ /g;
s/^ //;
s/\t/ /g;
@Data = split ( / /, $_ );
$Nf = @Data;
if ( $Nf == 5 )
{
( $DateA , $DateB , $DateC , $min , $kando ) = split ( / /, $_ );
if ( $DateA != '00000000' )
{
$countWC+= '1';
#print " 444 $DateA , $DateB , $DateC , $min , $kando 555\n";
$en = (2 * 0.5 * 3.1415 * 60 * $min * 2600 * 3500 * 20000 * 20000 * (0.5 * $kando * 0.00000001) * (0.5*$kando * 0.00000001));
#print "444 $en\n";
$YYYY = substr($DateA,0,4);
$MM1 = substr($DateA,4,2);
$DD = substr($DateA,6,2);
$HH = substr($DateB,0,2);
$MM = substr($DateB,2,2);
$Time = "${YYYY}-${MM1}-${DD}T${HH}:$MM";
$EN = sprintf ( "%10.5E", $en);
###printf OutFile ( "%s %s\n", $Time, $EN );
( $EN1, $EN2) = split ( /\+/, $EN);
($En1, $En2) = split ( /\./, $EN1 );
$EN3 = $EN2 + 1;
$AA = '0.';
$BB = '+';
printf OutFile ( "%s %s%s%s%s%02d\n", $Time, $AA, $En1, $En2, $BB, $EN3 );
if ( $countWC == '1' )
{
printf OutFileseki ( "%s %s%s%s%s%02d %s\n", $Time, $AA, $En1, $En2, $BB, $EN3, $countWC );
$enecum += $en;
}else{
$enecum += $en;
$enecum1 = sprintf ("%10.5E", $enecum);
($ENcum1, $ENcum2) = split ( /\+/, $enecum1);
($Encum1, $Encum2) = split ( /\./, $ENcum1 );
$ENcum3 = $ENcum2 + 1;
printf OutFileseki ( "%s %s%s%s%s%02d %s\n", $Time, $AA, $Encum1, $Encum2, $BB, $ENcum3, $countWC );
}
}
}
}
close ( InFile );
close ( OutFile );
close ( OutFileseki );
1ライナーperlでの積算方法有難うございました。
記憶に留めさせて頂きます。
補足に、自力で作ったperlのスクリプトを記述させて頂きました、まったくのperlの初心者でお恥ずかしいかぎりです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) awkの正規表現での最左最短マッチング 3 2022/07/01 00:10
- Perl Windows10においての『Perl』のプログラムについて 1 2022/05/09 16:04
- Access(アクセス) Access クエリ 同一テーブル内 複数フィールドの同時集計のやり方について 1 2022/05/18 19:01
- その他(教育・科学・学問) 画像の計算結果は間違いではありませんか? 1 2023/06/27 12:04
- 数学 数学の問題について 1 2023/02/13 18:40
- 数学 正体のわからない(^O^)2つの確率変数 X と Y の E[X]、E[Y]、E[XY] 2 2023/04/17 06:39
- Excel(エクセル) マクロだと数式が表示される 2 2022/09/10 14:48
- 数学 paythonを使用した周回積分に関する質問です。 2 2023/02/17 19:09
- 化学 次の問題について聞きたいことがあります。 様々な温度(t)で五酸化二炭素(N2O5)の分解反応の反応 3 2023/06/16 15:35
- C言語・C++・C# 3×3のラテン方陣をつくるプログラムを作成したのですが、(↓) #include <stdio.h> 5 2023/07/10 01:53
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
openした後、closeしないでプロ...
-
perlをバージョンアップしたら...
-
テキストファイルで提出とは?
-
Perlで時間の計算
-
アルファベットに付いて質問し...
-
perlでリテラル値はメモリにど...
-
TeraPadエディターの操作方法に...
-
Perlのエラーについてご教授く...
-
AI sisterとは、偽物の人ですか?
-
ファイルアイコンの左下に緑の□...
-
perlのrequireの動き方について...
-
perlのプログラミング 部分入れ...
-
Strawberry Perl for Windows ...
-
perl 初等プログラミングについて
-
arduino の割り込み処理について
-
#!/usr/bin/perlで書きだしたCG...
-
perlのflock関数でロックをかけ...
-
bashスクリプト
-
perlプログラミング 空白行削除
-
perlで2次元配列をサブルーチ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
テキストファイルで提出とは?
-
openした後、closeしないでプロ...
-
perlをバージョンアップしたら...
-
INDIRECT 横に再度抽出したい
-
Perl の外部モジュールの利用方法
-
Perlで特定文字列から特定文字...
-
Perlのエラーについてご教授く...
-
bashスクリプト
-
Strawberry Perl for Windows ...
-
perlで2次元配列をサブルーチ...
-
TeraPadエディターの操作方法に...
-
アルファベットに付いて質問し...
-
perlのflock関数でロックをかけ...
-
ファイルアイコンの左下に緑の□...
-
perlプログラミング 空白行削除
-
Wallpaper Engineでおすすめの...
-
Perlで時間の計算
-
perlのrequireの動き方について...
-
perlでリテラル値はメモリにど...
-
画像が表示でnull; this.src
おすすめ情報