1. 概要

Bashは浮動小数点演算をネイティブに実行できないことがわかっています。 ただし、除算を行うときに結果を丸めたい場合があります。 もちろん、さまざまな丸め要件があります。

このチュートリアルでは、Bashでさまざまな丸め方法を実行する方法を学習します。

2. 問題の紹介

3つの標準的な丸め方法があります。 実数xが与えられた場合:

  • フロアの丸め–出力はx以下の最大の整数です
  • 天井の丸め–結果は、x以上の最小の整数になります。
  • 半分の切り上げ– xの半分の値は常に切り上げられます

いくつかの例は、それらをすばやく理解するのに役立つ場合があります。

床の丸め 天井の丸め 半分の切り上げ
4/2 = 2 2 2 2
3/2 = 1.5 1 2 2
10/3=3.333… 3 4 3

このチュートリアルでは、正の整数の除算に焦点を当てます。

次に、Bashで各丸めメソッドを実装する方法を例を挙げて見てみましょう。

3. 床の丸め

Bashでは床の丸めを行うのは簡単です。 これは、Bashが自動的に除算によるフロア丸めを行うためです

次に、Bashの算術式の例をいくつか見てみましょう。

$ echo "floor rounding: 4/2 = $(( 4 / 2 ))"
floor rounding: 4/2 = 2
$ echo "floor rounding: 3/2 = $(( 3 / 2 ))"
floor rounding: 3/2 = 1
$ echo "floor rounding: 10/3 = $(( 10 / 3 ))"
floor rounding: 10/3 = 3

ご覧のとおり、ここで余分な作業を行う必要はありません。

4. 天井の丸め

床の丸めとは異なり、天井の丸めは独自に実装する必要があります。 このセクションでは、そのための2つの方法について説明します。

4.1. 剰余の使用

X /Yに天井の丸めを適用するとします。 1つのアイデアは、 X / Y R = X%Yの残りをチェックすることです。

  • R = 0 XYで割り切れるので、 X /Yが結果になります
  • R> 0 :結果は X / Y +1になります

さらに、 Bashの算術式は、Trueを1と評価し、Falseを0と評価します。

$ echo $(( 1 > 0 ))
1
$ echo $(( -1 > 0 ))
0

したがって、分割で天井の丸めを行うための式パターンを作成できます。

$(( ( X / Y ) + ( X % Y > 0 ) ))

次に、いくつかのテストを行いましょう。

$ echo "ceiling rounding: 4/2 = $(( ( 4 / 2 ) + ( 4 % 2 > 0 ) ))"
ceiling rounding: 4/2 = 2
$ echo "ceiling rounding: 3/2 = $(( ( 3 / 2 ) + ( 3 % 2 > 0 ) ))"
ceiling rounding: 3/2 = 2
$ echo "ceiling rounding: 10/3 = $(( ( 10 / 3 ) + ( 10 % 3 > 0 ) ))"
ceiling rounding: 10/3 = 4

上記のテストが示すように、期待どおりの結果が得られました。

4.2. 数学のトリックを使用する

余りをチェックすることで、除算に天井の丸めを適用する方法を学びました。

または、ちょっとした数学のトリックでそれを行うこともできます: Ceiling(X / Y)=(X + Y – 1)/ Y

それでは、最初に例を使用してテストし、機能するかどうかを確認しましょう。

$ echo "ceiling rounding: 4/2 = $(( ( 4 + 2 - 1 ) / 2 ))"
ceiling rounding: 4/2 = 2
$ echo "ceiling rounding: 3/2 = $(( ( 3 + 2 - 1 ) / 2 ))"
ceiling rounding: 3/2 = 2
$ echo "ceiling rounding: 10/3 = $(( ( 10 + 3 - 1 ) / 3 ))"
ceiling rounding: 10/3 = 4

良い結果が得られました。 次に、それが機能する理由を理解しましょう

X / Y の分割には、次の2つのケースがあります。

  • XYで均等に割り切れます: X = k * Y k は整数です)
  • バツで均等に割り切れない Y X = k * Y + r (( k r 両方とも整数であり、 0 )。

最初のケースを見てみましょう:

  • (X + Y – 1)/Yk* Y / Y +(Y – 1)/Yに分割できます。
  • Bashは常にフロアの丸めを除算に適用することを学びました。
  • したがって、(Y – 1)/ Y=0になります。
  • さらに、 k * Y / Y +(Y – 1)/ Y = k * Y / Y=k。 The k まさに私たちが得たい結果です。

次に、2番目のケースを見てみましょう。

  • X = k * Y + r がわかっているので、(X + Y – 1)/ Y (k * Y + r + Y – 1)と書くことができます。 / Y
  • 同様に、 k * Y / Y +(r + Y – 1)/Yに分割できます。

最初の部分は簡単です: k * Y / Y=k。 次に、2番目の部分を詳しく見てみましょう。

  • 私たちは知っています r 整数であり、 0 、だから私たちは Y = <(r + Y – 1)<2Y
  • したがって、(r + Y – 1)/ Y =1が得られます。
  • 最後に、XYで割り切れない場合、(X + Y – 1)/ Y = k +1。 これは、天井を丸めた後の期待される結果です。

ご覧のとおり、どちらの場合も正しい結果が得られます。

5. ハーフアップ丸め

5.1. 同様の数学のトリック

数学を使用して天井の丸めを行う方法を学びました。 同様に、半分の丸めについても同じ考えを採用できます。

Y –1の代わりにY/2Xに追加します。

したがって、次の式があります。 Half-up(X / Y)=(X + Y / 2)/ Y

次に、いくつかのテストを行いましょう。

$ echo "half-up rounding: 4/2 = $(( ( 4 + 2 / 2 ) / 2 ))"
half-up rounding: 4/2 = 2
$ echo "half-up rounding: 3/2 = $(( ( 3 + 2 / 2 ) / 2 ))"
half-up rounding: 3/2 = 2
$ echo "half-up rounding: 10/3 = $(( ( 10 + 3 / 2 ) / 3 ))"
half-up rounding: 10/3 = 3

上記の出力が示すように、期待どおりの結果が得られました。

5.2. printf“ %.0f” を使用してみませんか?

前のセクションで、ハーフアップ丸めを行う式を学習しました。

ただし、実際には、printfコマンドまたはprintf関数を使用してハーフアップ丸めを実行するコードが表示される場合があります。

いくつかの例を見てみましょう。

$ printf "half-up rounding: 3/2 = %.0f\n" $( echo "scale=2; 3 / 2" | bc)
half-up rounding: 3/2 = 2

$ awk 'BEGIN { printf "half-up rounding: 3/2 = %.0f\n", 3 / 2 }'
half-up rounding: 3/2 = 2

最初の例では、bcコマンドを使用して3/2を計算し、printfコマンドでフォーマット印刷を実行します。

printf コマンドは、Cのprintf関数の仕様に従います。 フォーマット文字列「%.0f」は、浮動小数点精度を0に設定します。 つまり、整数部分のみを保持します。 また、 printf 最も近い整数に丸められます。

2番目のawkの例では、printfコマンドは実行されません。 代わりに、awkは独自のprintfステートメントを使用してフォーマット印刷を実行します。

awkprintfステートメントは、Cのprintf関数と同じルールに従います。 したがって、最初の例とほとんど同じです。

上記の出力が示すように、 3/2 を計算したとき、両方の例で正解が得られました。

ただし、コーナーケースは両方のコマンドを壊します

$ printf "half-up rounding: 1/2 = %.0f\n" $( echo "scale=2; 1 / 2" | bc)
half-up rounding: 1/2 = 0

$ awk 'BEGIN { printf "half-up rounding: 1/2 = %.0f\n", 1 / 2 }'
half-up rounding: 1/2 = 0

上記のテストが示すように、今回は1/2を計算します。 結果は0.5であることがわかります。 したがって、半分の丸めの後、1を取得することを期待しています。 ただし、どちらのコマンドでも0が得られました。

これは、フォーマットが「%.0f」のprintfが1ではなく0.5から0に丸められるためです。

$ printf "%.0f\n" 0.5 
0

最後に、数学的なアプローチで同じ計算をテストしてみましょう。

$ echo "half-up rounding: 1/2 = $(( ( 1 + 2 / 2 ) / 2 ))"
half-up rounding: 1/2 = 1

上記の出力が示すように、(X + Y / 2)/Yアプローチは正しい結果をもたらします。

6. 結論

この記事では、Bashの除算計算にさまざまな丸め方法を適用する方法について説明しました。 それらを表にまとめましょう。

丸め方法 X / Y
床の丸め X / Y
天井の丸め (X + Y – 1)/ Y または(X / Y)+(X%Y> 0)
ハーフアップ丸め (X + Y / 2)/ Y

さらに、printfアプローチはハーフアップ丸めの安定したソリューションではないことを学びました。