ゼロで除算を無視またはキャプチャします。

ゼロで除算を無視またはキャプチャします。

Bashでゼロ除算エラーを無視する方法は?

例 1: (動作しない)

echo $((1/0)); echo "yay";
echo $((1/0)) || echo "yay";

例2:

echo -n $(echo -n $((1/0))) 2> /dev/null; echo "yay";

0で除算する場合、特定の値をデフォルトとして使用する例2よりも簡単な方法はありますか?

答え1

Bashにはゼロで除算する方法はなく、ash、ksh93、pdksh、zshも同様です。ゼロで除算する唯一の方法は、除算が発生する前に検出するか(除算を実行する前に各分母を確認する)、サブシェルで除算を実行することです。

サブシェルで算術演算を実行している場合は、サブシェルの終了状態を使用してエラーが発生したかどうかを確認できます(ゼロまたは他のエラーに分割)。

x=$(echo $(($a/$b)))
if [ $? -ne 0 ]; then
  echo "$b is 0 or some other arithmetic error occurred"
fi

答え2

まあ、if (($divisor == 0)); then SHUT_DOWN_EVERYTHING;私の考えではサブシェルを使うことができると思います。

(echo $((1/0))) 2>/dev/null || echo yay

しかし、これは要求された「デフォルト」ではなくサンプルコードのエラーを自動的に無視するので、何をしようとしているのか説明しませんか?

答え3

SIGFPE(信号番号8)は、おそらくここでキャッチする必要がある信号です。

このシグナル用のシグナルハンドラを取り付けます。

trap "echo divide by zero >&2 ; exit 1 " SIGFPE

更新:bashにはオーバーライドできない独自のハンドラがあるようです。ソリューションを通常のCプログラムからbash構文に移動しました。

うーん - この方法は他のトラップでも機能します。

答え4

私たちはスクリプトで小さな機能を使用します

#!/bin/sh
divisor_valid "$myvar" || myvar=1
x=$(( 1000 / myvar ))
y=$(( 1000 % myvar ))

これにより、まだ読みやすくなり、CPU集約的なサブシェルを回避できます。

ヘルパー機能は次のとおりです。

isnumber(){ test 2>/dev/null ${1:-a} -eq "${1##*[!0-9-]*}";}
divisor_valid(){ isnumber $1||return;case $1 in 0|-0)false;;esac;}

busybox-ashを使用していますが、POSIX(tm)でも動作します。

関連情報