シェルの浮動小数点比較

シェルの浮動小数点比較

これに基づいて、シェルスクリプトで浮動小数点値を比較しています。引用する。以下はスクリプトの内容です

num1=50.960
num2=6.65E+07
echo "${num1} < ${num2}" | bc

スクリプトを実行すると、出力は「0」です。しかし、比較によると「1」でなければなりません。比較が期待どおりに機能しない理由を理解する必要がありますか?

答え1

ユーティリティは目的の番号をbc認識しません。6.65E+07

OpenBSDではE16進数なので6.65E6.664(6.65 + 0.014)で、+077を足すと13.664になりますが、これは明らかに50.960より小さいです。 GNUシステムでも、6.65Eこれは6.659あなたが望むものではありません。

代わりにnum2文字列6.65*10^7または66500000

$ num1=50.960; num2='6.65*10^7'; printf '%s < %s\n' "$num1" "$num2" | bc
1

答え2

num2をそのまま使用するには、awkを使用できます。

awk -v num1="$num1" -v num2="$num2" 'BEGIN{exit num1<=num2}'

2つの数字を比較して、num1がnum2より小さい場合は1を終了し、そうでない場合は0を終了します。

注:num1とnum2が同じ場合、1は終了します。これは、この場合bcで見られるのと同じ動作です。この場合、0を終了するにはを使用する必要が<あります<=

答え3

dc1つの方法は、まず工学表記を浮動小数点に変換してこのユーティリティを使用することです。

num1=50.960
num2=6.65E+07

set -- "$num1" "$num2"

e2f() {
  case $1 in
    *[eE]*) :;;
    *) set -- "$1e0"
  esac
  set -- "${1//+/}"
  set -- "${1//-/  _}"
  set -- "${1//[eE]/ 10 }"
  echo "$1^*"
}

eCmp() {
  test "$(dc -e "
15k[1p]sa$(e2f "$1") $(e2f "$2")r>a")" = 1
}

## and then...
if eCmp "$@"
then
  echo "$1 > $2"
else
  echo "$1 <= $2"
fi

出力:

50.960 <= 6.65E+07

答え4

はい、bcさまざまな数学演算を実行できます。しかし、ワゴンを理解していません。最新のシェルのprintfは浮動小数点数を理解できますが、数学はできません。

彼らと一緒にしましょう:

$ num1=50.960
$ num2=6.65E+07
$ printf '%f < %f\n' "$num1" "$num2" | bc -l
1

関連情報