Perl / awkでシェルスクリプトを使用して二乗和を計算する

Perl / awkでシェルスクリプトを使用して二乗和を計算する

以下のように2つのファイルがあります。

ファイル1

0.34
0.27
0.32

ファイル2

0.15
0.21
0.15

では、各列間の平方和を計算したいと思います。例えば、

[(0.34 - 0.15)^2 + (0.27 - 0.21)^2 + (0.32 - 0.15)^2 ] / 3

どこサムファイルの総行数。どちらのファイルも同じ数の行を持ちます。

私は次のbashスクリプトを思い出してうまくいきますが、他のより簡単な方法があるかどうか疑問に思います。

#! /bin/bash   
sum=0.0
while true; do
  read -r lineA <&3
  read -r lineB <&4
  if [ -z "$lineA" -o -z "$lineB" ]; then
    break
  fi
diff=$(bc <<< "scale=5; $lineA - $lineB")
square=$(bc <<< "scale=5; $diff*$diff")
sum=$(bc <<< "scale=5; $sum+$square")
done 3<file1 4<file2
filelen=`wc -l file1 | cut -f1 -d' '`
final=$(bc <<< "scale=5; $sum/$filelen")
echo "$final"

awkそれとももっと簡単な方法がありますかperl

編集する

入力ファイルには200万行があり、入力ファイルには実際には次のような科学的な数字が含まれています。

3.59564e-185

私のスクリプトと提案された答えは科学的な数字で失敗します。ただし、科学的な数字を記号に変更すると、問題のスクリプトを機能させることができます10^

入力ファイルを次のように変換しました。

sed -e 's/[eE]+*/\*10\^/' file1 > file1_converted
sed -e 's/[eE]+*/\*10\^/' file2 > file2_converted

これで、提案された2つの回答が失敗し、エラーメッセージが表示されますNan。私のスクリプトはうまくいくようですが、200万行の場合は実行に時間がかかります。

効率的に動作させる方法はありますか?

答え1

paste1つの方法は、ファイルの行数が同じであるため、これを使用することです。

paste file1 file2 | awk '{s += ($1-$2)^2}; END{print (s+0)/NR}'
0.0228667

答え2

awk 'FNR==NR { file1[NR]=$1; next; }; { diff=$1-file1[FNR]; sum+=diff^2;}; 
  END { print sum/FNR; }' file1 file2

答え3

perl大きな浮動小数点データの場合は、次のものを使用できますbignum

$ paste file1 file2 | perl -Mbignum -anle '
    $sum += ($F[0] - $F[1])**2;
    END {     
        print $sum/$.;
    }                
'
0.02286666666666666666666666666666666666667

関連情報