bcを正しく使用してパーセンテージ値を浮動小数点形式に変換するには?

bcを正しく使用してパーセンテージ値を浮動小数点形式に変換するには?

3つの変数と値があります。

totalLines=14
outsideLines=6
multiplied=600

totalLines合計行数(100%)を表し、outsideLinesタイムスタンプ値が特定の制限を超える行数を示します。私の目的は、これらの外部線の割合を計算することです。私がこうすれば:

percentage=$(( multiplied / totalLines))

echoの$percentage結果を得た。

42

しかし、次のように浮動小数点数のパーセンテージを生成したいと思います。

42.85

私はこれを達成しようとしています。

percentage=$( bc <<< 'scale=2; $multiplied / $totalLines' )

次のエラーで失敗します。

(standard_in) 1: illegal character: $
(standard_in) 1: illegal character: $
(standard_in) 1: illegal character: L
(standard_in) 1: syntax error

浮動小数点数のパーセンテージを取得するには、bcをどのように正しく使用する必要がありますか?

ベストアンサー1

シンプル

実行する必要がある(近似、ゼロに丸め)数学のみの場合は、次のようにほとんどのシェルで直接計算を実行できます。

➤ printf '%8.2f\n' "$((multiplied*100/totalLines))e-2"
42.85

そして、最新バージョンのbash、zsh、またはksh93では、次のように変数に割り当てることができます。

➤ printf -v percentage '%.2f\n' "$((multiplied*100/totalLines))e-2"
➤ echo "$percentage"
42.85

これは整数演算、小数点以下の2桁、空白なしでゼロに丸められたパーセンテージです。

これは、シェルが整数の数学を実行しますが、常に100を掛けた値を計算できるためです。$((…))その結果、整数は4285になります。

次に、小数点区切り記号(点)を左に2桁移動するだけです。

そのため、e-2その価値はそのままです4285e-2
結果は、小数点以下の2桁の浮動小数点数としてフォーマットされます%8.2f

移植性が高いオプションですが、少し遅くなります(サブシェルはフォーク()を意味します)。ほとんどのシェルでは以下を使用します。

percentage="$(printf '%8.2f\n' "$((outsideLines*100*100/totalLines))e-2")"

これはすべてシェル内で行われます(printfが組み込まれている場合)。
外部アプリケーションをロードする必要はありません。これにより速度が速くなり、CPU負荷が軽減されます(例:一つ数字)。

1000文字まで拡張しようとしないでください。シェルはテキストファイルの操作に適したツールではありません。

最近

パーセンテージを最も近い偶数に丸める必要がある場合。 IEEE-754の基本的な丸め方法では、小数部にはより多くの桁を使用する必要があります。次のようにすると、より多くの数字(この場合は13(小数点11桁))が得られます。

$ printf '%.2f\n' "$((outsideLines*10**15/totalLines))e-13"
62.75

$ printf '%.4f\n' "$((outsideLines*10**15/totalLines))e-13"
62.7451

$ printf '%.6f\n' "$((outsideLines*10**15/totalLines))e-13"
62.745098

シェルの整数計算から小数点以下11桁以上を抽出することは意味がありません。倍精度浮動小数点数は(通常)53ビットに制限され、10進数は16ビットを超えません。パーセント数字の整数部分に使用される2桁の数字を減算すると、小数点以下14桁以下が残ります。パーセンテージが小さいほど値が小さくなる(数学は整数値で行われるため)、小数点以下11桁以下しか信頼できません。

紀元前

より高い精度(非常に小さいパーセント)が必要な場合は、シェルの整数数学を使用することは意味がありません。この場合は、bc直接使用してください(外部プログラムのロードと実行が遅くなります)。

$ bc <<<"scale=30; outsidelines=$outsideLines; totallines=$totalLines; outsidelines*100/totallines"

42.857142857142857142857142857142

$ val="$(bc <<<"scale=30; outsidelines=$outsideLines; totallines=$totalLines; outsidelines*100/totallines")"

$ printf '%.8f' "$val"
42.85714286

$ printf '%.6f' "$val"
42.857143

$ printf '%.4f' "$val"
42.8571

$ printf '%.2f' "$val"
42.86

1 シェル整数算術ラウンド0になる傾向がある。ここでは取り除く42.85714285714285...ために切りました。42.850.00714285714285

²オペレーティングシステムのデフォルトの丸めモードに従って丸めます。通常、最も近い値は偶数と同じです(銀行家の丸め(ただし、一部のオペレーティングシステムでは0に最も近い関係かもしれません。)これは小数点11桁を使用して行われます。たとえば、計算された値が2桁に近い場合、42.86この値は印刷されます。

おすすめ記事