Java rounding up to an int using Math.ceil

int total = (int) Math.ceil(157/32);

Why does it still return 4? 157/32 = 4.90625, I need to round up, I've looked around and this seems to be the right method.

I tried total as double type, but get 4.0.

What am I doing wrong?

188234 次浏览

157/32 is int/int, which results in an int.

Try using the double literal - 157/32d, which is int/double, which results in a double.

157/32是一个整数除法,因为所有的数值文字都是整数,除非另外指定了一个后缀(d表示双 l表示长)

除法被四舍五入(到4) ,然后它被转换成一个双(4.0) ,然后四舍五入(到4.0)

if you use a variables you can avoid that

double a1=157;
double a2=32;
int total = (int) Math.ceil(a1/a2);
int total = (int) Math.ceil((double)157/32);

也可以把一个数字从整数转换成实数,你可以加上一个点:

int total = (int) Math.ceil(157/32.);

(157/32.)的结果也是真实的

int total = (int) Math.ceil( (double)157/ (double) 32);

你正在做的是 157/32,它将两个整数相除,总是得到一个四舍五入的整数。因此 (int) Math.ceil(...)没有任何作用。有三种可能的方法可以达到你想要的效果。我使用 选择1选择2recommend。请使用 选项0

选项0

ab转换为双精度,可以按照需要使用除法和 Math.ceil。然而,我强烈反对使用这种方法,因为双除法可能是不精确的。要了解有关双精度不精确的更多信息,请参见 这个问题

int n = (int) Math.ceil((double) a / b));

选择一

int n = a / b + ((a % b == 0) ? 0 : 1);

如果 ab都是整数,则始终使用地板执行 a / b。然后有一个内联 if 语句,用于检查是否应该使用 ceil 而不是 floor。所以 + 1或者 + 0,如果有一个除法余数,你需要 + 1。a % b == 0检查余数。

选择二

这个选项非常短,但是对于一些不太直观的人来说可能是这样。我认为这种不那么直观的方法会比双重除法和比较法更快:
请注意,这不适用于 b < 0

int n = (a + b - 1) / b;

为了减少溢出的可能性,您可以使用以下方法。但是请注意,它不工作的 a = 0b < 1

int n = (a - 1) / b + 1;

“缺乏直觉的方法”背后的解释

因为在 Java (和大多数其他编程语言)中除以两个整数总是会得到最后的结果,所以:

int a, b;
int result = a/b (is the same as floor(a/b) )

但是我们不需要 floor(a/b),而是需要 ceil(a/b),并使用 维基百科中的定义和图形:enter image description here

通过这些地板和天花板函数的图,您可以看到它们之间的关系。

Floor function Ceil function

你可以看到 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) )

这不是一个真正的证据,但我希望你对此感到满意。如果有人能解释得更好,我也会很感激的。也许在 数学溢出上问问。

在 Java 中,添加一个.0将使它成为一个双..。

int total = (int) Math.ceil(157.0 / 32.0);
int total = (157-1)/32 + 1

或者更一般

(a-1)/b +1

使用双重投像

Math.ceil((double)value)之类的

Math.ceil((double)value1/(double)value2);

除两个整数时,

int c = (int) a / (int) b;

结果是 int,其值为 a除以 b,四舍五入为零。因为结果已经是四舍五入的,所以 ceil()不做任何事情。请注意,这个舍入不同于 floor(),后者向负无穷大舍入。因此,3/2等于 1(floor(1.5)等于 1.0,但是 (-3)/2等于 a0(但是 a1等于 a2)。

这很重要,因为如果 a/b总是与 floor(a / (double) b)相同,那么您可以将 a/bceil()实现为 -( (-a) / b)

建议从以下几个方面获取 ceil(a/b)

int n = (a + b - 1) / b;,相当于 a / b + (b - 1) / b(a - 1) / b + 1

因为 ceil(a/b)总是大于 floor(a/b),除非 a/b是一个整数。因此,您希望将它提升到(或超过)下一个整数,除非 a/b是一个整数。添加 1 - 1 / b就可以做到这一点。对于整数,它不会把它们推到下一个整数。至于其他的,会的。

哎呀。希望这是有意义的。我相信有一个更精确的数学方法来解释它。

检查下面的解决方案来回答你的问题:

int total = (int) Math.ceil(157/32);

这里你应该乘以分子与1.0,然后它会给你的答案。

int total = (int) Math.ceil(157*1.0/32);

Java 默认只提供楼层分区 /,但是我们可以提供 以楼面为单位书写天花板。让我们看看:

任何整数 y都可以用形式 y == q*k+r来写。根据楼层划分(这里是 floor)的定义,

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


然后将第一个方程代入第三个方程,得到 q

ceil(q*k+r+1, k) == floor(q*k+r, k) + 1  , where 0 ≤ r ≤ k-1

最后,给出任意整数 y,其中 y = q*k+r+1对于某些 qkr,我们有

ceil(y, k) == floor(y-1, k) + 1

我们完事了,希望这能帮上忙。

没有人提到最直观的:

int x = (int) Math.round(Math.ceil((double) 157 / 32));

解决了 双倍除法不精确的问题。

有两种方法可以四舍五入你的双值。

  1. Math.ceil
  2. 数学,地板

如果你想你的答案4.90625为4,那么你应该使用 Math.floor,如果你想你的答案4.90625为5,那么你可以使用 Math.ceil

You can refer following code for that.

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);


}


}

我知道这是一个老问题,但在我看来,我们有一个更好的方法是使用 BigDecimal,以避免精度损失。顺便说一下,使用这个解决方案,我们有可能使用几个舍入和规模策略。

final var dividend = BigDecimal.valueOf(157);
final var divisor = BigDecimal.valueOf(32);
final var result = dividend.divide(divisor, RoundingMode.CEILING).intValue();