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