Bashの浮動小数点値の比較

Bashの浮動小数点値の比較

私のif式は常にTRUEと評価されます。 ROTATION変数は0.000または90.000の浮動小数点値です。

ROTATION="$(mediainfo --Inform="Video;%Rotation%" $VIDEO$ORIGINALEXTENTION)"
echo $ROTATION

ROTATION_PARAMETER=""

if [ $ROTATION -eq 90 ]
then
    ROTATION_PARAMETER=" --rotate=4"
fi

echo $ROTATION_PARAMETER

変数と値を比較する方法は?

答え1

これを達成するには、bcコマンドを使用できます。

echo "$ROTATION == 90"|bc

偽であれば0を取得し、真であれば1を取得します。

PS同等の浮動小数点数の比較は、プログラミングの最も賢明な方法ではないことに注意してください。 :)

答え2

文字列なので、連結された複数の文字列を互いに比較することができます。バランスのとれた値は、複数のシェルテストを同時に処理する簡単な方法を提供します。

[ "${num#90.}${num%[!0]*}" = "90${num%[!0]*}" ] && do_it

ただし、これは$num絶対数の場合にのみ機能します。次の整数値を検証できます$num

[ "$num" -eq "$num" ]

または次の浮動小数点:

[ "${#num}${num#*.}" -ne "${num%.*}${#num}" ]

しかし、case一般的に最良の方法は...

case ".${num##*[!-.0-9]*}" in
(.|.[!9]*|.9[!0]*|.90.*[!0]*) 
! :;;esac 

外部ユーティリティに関する限り、私は通常、任意のシステムコマンドを実行するために使用できるので、dcこれを好みます。bc

dc -e '[!echo execute arbitrary system command]s=' \
   -e '90 90.0 =='

括弧内のすべての内容[]は文字列であり、メインスタックの最初の2つの値がコマンドで実行されるsと、名前付き配列に格納されます。=dc(ここでは90と90.0) =もう一つ。!文字列の最初の演算子は、次の!すべての演算子をシステムコマンドとして実行する演算子です。演算子を使用して、条件付き実行のためにdc入力からより多くのスクリプトを読み取ることもできます。?

しかし、式の-e構文はGNUismです。 Heredocを使用して同じ効果を得るか、コマンドを標準入力に再パイプすることができます。

たとえば、

! dc -e '[!kill -PIPE "$PPID"]s= 90 90.0 ==' && do_it

答え3

文字列のように値を比較できます。

{ printf "[ %.3f == %.3f ]\n" $ROTATION 90 | bash ; } && ROTATION_PARAMETER=" --rotate=4"

でも

[ $(printf "%.3f == %.3f" $ROTATION 90) ] && ROTATION_PARAMETER=" --rotate=4"

一部のロケールには小数点区切り文字が必要なため、その,形式を使用する必要があります。.$ROTATION90,000

答え4

次のように、浮動小数点値の処理に適したスクリプト言語を呼び出すことを検討してください。

ROTATION=...
if $( perl -e 'use POSIX "fmod";if(fmod($ENV{ROTATION}, 90.0)<0.001) {exit(0)} else{exit(1)}' )
then...

(おそらくリバース終了戻りコードを使用)

関連情報