GNU/Linux >> Linux の 問題 >  >> Linux

bcを使用せずにシェルスクリプトで丸められたパーセンテージを計算する

integer をサポートするためにのみ、POSIX 準拠のシェル スクリプトが必要です。 シェル言語を使用した算術演算 (「符号付き長整数演算のみが必要です」)、したがって、純粋なシェル ソリューションはエミュレートする必要があります 浮動小数点演算:

item=30
total=70

percent=$(( 100 * item / total + (1000 * item / total % 10 >= 5 ? 1 : 0) ))
  • 100 * item / total 切り捨てられた 整数の結果 パーセンテージとしての分割
  • 1000 * item / total % 10 >= 5 ? 1 : 0 小数点第 1 位を計算し、それが 5 以上の場合は、整数の結果に 1 を加えて切り上げます。
  • ないことに注意してください 変数参照の前に $ を付ける必要があります 算術展開 $((...)) 内 .

If - 質問の前提に反して - 外部ユーティリティの使用 可:

  • awk シンプルを提供します ただし、これには注意が伴います 真の倍精度 binary を使用すること 浮動小数点値であるため、decimal で予期しない結果が生じる可能性があります 表現 - 例:printf '%.0f\n' 28.5 を試してください 、これは 28 を生成します 予想される 29 ではなく ):
awk -v item=30 -v total=70 'BEGIN { printf "%.0f\n", 100 * item / total }'
  • -v の方法に注意してください awk の変数を定義するために使用されます 一重引用符の間の明確な分離を可能にするスクリプト したがって、文字通り awk スクリプトとシェルから渡された値 .
  • 対照的に、bc でも POSIX ユーティリティ (したがって、ほとんどの Unix ライクなプラットフォームに存在することが期待できます) であり、任意精度 を実行します 算術、それは常に切り捨てる 結果、丸め 別の人が実行する必要があります 効用; printf ただし、原則として POSIX ユーティリティですが、必須ではありません 浮動小数点フォーマット指定子をサポートする (awk 内で使用されるなど) 上記)、したがって、次の機能する場合と機能しない場合があります (より単純な awk を考えると、手間をかける価値はありません 解決策であり、浮動小数点演算による精度の問題が再び発生したことを考えると):
# !! This MAY work on your platform, but is NOT POSIX-compliant:
# `-l` tells `bc` to set the precision to 20 decimal places, `printf '%.0f\n'`
# then performs the rounding to an integer.
item=20 total=70
printf '%.0f\n' "$(bc -l <<EOF
100 * $item / $total
EOF
)"


AWK を使用する (バッシュイズムなし):

item=30
total=70
percent=$(awk "BEGIN { pc=100*${item}/${total}; i=int(pc); print (pc-i<0.5)?i:i+1 }")

echo $percent
43

元のパーセント計算の 2 * を取り、そのモジュロ 2 を取得すると、丸めの増分が得られます。

item=30
total=70
percent=$((200*$item/$total % 2 + 100*$item/$total))

echo $percent
43

(bash、ash、dash、ksh でテスト済み)

これは、AWK コプロセスを起動するよりも高速な実装です:

$ pa() { for i in `seq 0 1000`; do pc=$(awk "BEGIN { pc=100*${item}/${total}; i=int(pc); print (pc-i<0.5)?i:i+1 }"); done; }
$ time pa

real    0m24.686s
user    0m0.376s
sys     0m22.828s

$ pb() { for i in `seq 0 1000`; do pc=$((200*$item/$total % 2 + 100*$item/$total)); done; }
$ time pb

real    0m0.035s
user    0m0.000s
sys     0m0.012s

Linux
  1. ディスク使用量が90%を超えた場合にアラートメールを送信するシェルスクリプト?

  2. 追加のツールを使用せずに実行可能バイナリをシェルスクリプトに埋め込む方法は?

  3. LfのないXmlは、シェルでSedコマンドを使用してきれいにしたいですか?

  1. Bash スクリプト:セッションをログに記録するための bash スクリプトからのスクリプト コマンドの使用

  2. BASHスクリプトで「awk」を使用してCSVファイルの最後に列を追加します

  3. シェルで .sh 拡張子のないファイルを実行する方法

  1. シェル スクリプトを使用して $PATH 変数を反復処理する

  2. grep と awk の使用

  3. シェル:「sleep」を使わずにコマンドを遅らせることは可能ですか?