回答:
あなたはやっているの157/32
は常に丸いダウン整数にお互いに2つの整数を、除算されています。したがって、(int) Math.ceil(...)
何もしていません。あなたが望むものを達成するための3つの可能な解決策があります。オプション1またはオプション2の使用をお勧めします。オプション0は使用しないでください。
##オプション0
変換してdoubleに変換するa
とb
、除算を使用Math.ceil
して希望どおりに機能させることができます。ただし、二重除算は不正確になる可能性があるため、このアプローチの使用はお勧めしません。ダブルスの不正確さの詳細については、この質問を参照してください。
int n = (int) Math.ceil((double) a / b));
##オプション1
int n = a / b + ((a % b == 0) ? 0 : 1);
あなたは行うa / b
場合は、常に床とa
し、b
両方とも整数です。次に、インラインのifステートメントの魔女が、床の代わりに天井を張るべきかどうかをチェックします。したがって、+ 1または+0、除算の剰余がある場合は+1が必要です。a % b == 0
残りをチェックします。
##オプション2
このオプションは非常に短いですが、おそらく直感的ではありません。このあまり直感的でないアプローチは、二重除算および比較アプローチよりも高速だと思います。
これは、では機能しないことに注意してくださいb < 0
。
int n = (a + b - 1) / b;
オーバーフローの可能性を減らすために、以下を使用できます。ただし、a = 0
およびでは機能しないことに注意してくださいb < 1
。
int n = (a - 1) / b + 1;
##「直感的でないアプローチ」の背後にある説明
Java(および他のほとんどのプログラミング言語)で2つの整数を除算すると、常に結果がフロアされます。そう:
int a, b;
int result = a/b (is the same as floor(a/b) )
しかし、私たちは望んfloor(a/b)
でいませんがceil(a/b)
、ウィキペディアの定義とプロットを使用します:
これらのfloorおよびceil関数のプロットを使用すると、関係を確認できます。
あなたはそれを見ることができますfloor(x) <= ceil(x)
。必要floor(x + s) = ceil(x)
です。したがって、を見つける必要がありますs
。私たちが1/2 <= s < 1
それをとれば、ちょうどいいでしょう(いくつかの数字を試してみて、あなたがそれを見るでしょう、私はこれを証明するのが難しいと思います)。そして1/2 <= (b-1) / b < 1
、
ceil(a/b) = floor(a/b + s)
= floor(a/b + (b-1)/b)
= floor( (a+b-1)/b) )
これは本当の証拠ではありませんが、あなたがそれに満足していることを望みます。誰かがそれをよりよく説明できれば私もそれを感謝します。MathOverflowで質問してください。
157/32はでint/int
、結果はになりint
ます。
-ダブルリテラル使用してみてください157/32d
で、int/double
、で結果をdouble
。
誰も最も直感的に言及していません:
int x = (int) Math.round(Math.ceil((double) 157 / 32));
このソリューションは、二重除算の不正確さを修正します。
たとえば、2つの整数を除算する場合
int c = (int) a / (int) b;
結果はでありint
、その値はでa
除算されb
、ゼロに向かって丸められます。結果はすでに丸められているため、ceil()
何もしません。この丸めはfloor()
、負の無限大に丸めると同じではないことに注意してください。したがって、3/2
等しい1
(およびfloor(1.5)
等しいが1.0
、(-3)/2
等しい-1
(ただしfloor(-1.5)
等しい-2.0
))。
これが重要なのa/b
は、常にと同じである場合、asをfloor(a / (double) b)
実装するだけceil()
でよいa/b
ため-( (-a) / b)
です。
取得の提案ceil(a/b)
から
int n = (a + b - 1) / b;
、またはと同等a / b + (b - 1) / b
、または(a - 1) / b + 1
ので、作品ceil(a/b)
より1つの大きいが常にあるfloor(a/b)
場合を除き、a/b
全体の数です。したがって、が整数でない限り、次の整数に(または過去に)バンプする必要がありますa/b
。これを追加する1 - 1 / b
と追加されます。整数の場合、それらを次の整数に押し上げることはありません。他のすべてのために、それはします。
うわぁ。うまくいけば、それは理にかなっています。それを説明するより数学的にエレガントな方法があると私は確信しています。
また、数値を整数から実数に変換するには、ドットを追加できます。
int total = (int) Math.ceil(157/32.);
そして、(157/32)の結果も本物になります。;)
/
デフォルトでは、Javaはフロアディビジョンのみを提供します。しかし、私たちは床の観点から天井を書くことができます。どれどれ:
整数y
はの形式で記述できますy == q*k+r
。四捨五入する階分割(ここfloor
)の定義によればr
、
floor(q*k+r, k) == q , where 0 ≤ r ≤ k-1
切り上げる天井分割(ここceil
)のr₁
、
ceil(q*k+r₁, k) == q+1 , where 1 ≤ r₁ ≤ k
代わりにr+1
使用できる場所r₁
:
ceil(q*k+r+1, k) == q+1 , where 0 ≤ r ≤ k-1
次に、最初の方程式を3番目の方程式に代入しq
て
ceil(q*k+r+1, k) == floor(q*k+r, k) + 1 , where 0 ≤ r ≤ k-1
最後に、任意の整数与えられたいくつかのために、、、私たちは持っているがy
y = q*k+r+1
q
k
r
ceil(y, k) == floor(y-1, k) + 1
これで完了です。お役に立てれば。
ceil
なので、特に私たちが整数のセル、つまりr1 = kをとっている場合、最初の定義からそのように定義されている理由は明確ではありません。エッジケースはこれについてトリッキーですので、もう少し詳しく説明する必要があると思います。
double値を切り上げる方法は2つあります。
回答4.90625を4にしたい場合は、Math.floorを使用し、回答4.90625を5にしたい場合は、Math.ceilを使用できます。
そのために以下のコードを参照できます。
public class TestClass {
public static void main(String[] args) {
int floorValue = (int) Math.floor((double)157 / 32);
int ceilValue = (int) Math.ceil((double)157 / 32);
System.out.println("Floor: "+floorValue);
System.out.println("Ceil: "+ceilValue);
}
}
int total = (157-1)/32 + 1
より一般的な
(a-1)/b +1