Java使用Math.ceil四舍五入到int

时间:2011-08-21 16:02:10

标签: java math

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

为什么它仍然会返回4? 157/32 = 4.90625,我需要围捕,我环顾四周,这似乎是正确的方法。

我尝试将total作为double类型,但获得了4.0。

我做错了什么?

15 个答案:

答案 0 :(得分:154)

你正在做157/32,它将两个整数相互划分,这总是导致一个向下舍入的整数。因此(int) Math.ceil(...)没有做任何事情。有三种可能的解决方案可以实现您的目标。我推荐使用选项1 选项2 。请使用选项0

选项0

ab转换为double,您可以根据需要使用除法和Math.ceil。但是我强烈反对使用这种方法,因为双重划分可能是不精确的。要阅读有关双精度不精确的更多信息,请参阅this question

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

选项1

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

如果a / ba都是整数,则b始终为a % b == 0。然后你有一个内联if语句巫婆检查你是否应该ceil而不是floor。所以+1或+0,如果有除法的余数,则需要+1。 int n = (a + b - 1) / b; 检查剩余部分。

选项2

此选项非常短,但可能对某些不太直观。我认为这种不那么直观的方法比双重分割和比较方法更快:

a = 0

为了减少溢出的可能性,您可以使用以下内容。但请注意,它不适用于b < 1int n = (a - 1) / b + 1;

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

“不太直观的方法”背后的解释

由于在Java(以及大多数其他编程语言)中分割两个整数,因此总是将结果置于底层。所以:

floor(a/b)

但我们不希望ceil(a/b),而是floor(x) <= ceil(x),并使用Wikipedia中的定义和图表:enter image description here

通过这些地板和ceil功能图可以看出这种关系。

Floor function Ceil function

您可以看到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) ) ,所以

{{1}}

这不是一个真实的证明,但我希望你对它感到满意。如果有人能够更好地解释它,我也会很感激。也许在MathOverflow上询问。

答案 1 :(得分:57)

157/32为int/int,结果为int

尝试使用双{ - 1}} 157/32d,这会产生int/double

答案 2 :(得分:34)

157/32是一个整数除法,因为所有数字文字都是整数,除非另外指定后缀(d用于加倍l

除非转换为双精度(4.0),然后向上舍入(至4.0)

,将除法向下舍入(至4)

如果您使用变量,则可以避免

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

答案 3 :(得分:24)

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

答案 4 :(得分:3)

在Java中添加.0会使它成为双倍......

int total = (int) Math.ceil(157.0 / 32.0);

答案 5 :(得分:3)

分割两个整数时,例如,

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)等于{{1} }})。

这很重要,因为如果-2.0始终与a/b相同,那么您只需将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),除非floor(a/b)是整数。因此,除非a/b是整数,否则您希望将其提升到(或超过)下一个整数。添加a/b即可。对于整数而言,它不会将它们推向下一个整数。对于其他一切,它会。

让人惊讶。希望这是有道理的。我确信这是一种更加数学上优雅的方式来解释它。

答案 6 :(得分:2)

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

答案 7 :(得分:1)

另外,要将数字从整数转换为实数,您可以添加一个点:

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

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

答案 8 :(得分:1)

检查以下解决方案以获取您的问题:

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

在这里你应该将Numerator与1.0相乘,然后它会给出你的答案。

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

答案 9 :(得分:1)

没人提到最直观的:

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

此解决方案修复了 double 除法不精确。

答案 10 :(得分:1)

您可以通过两种方法对双倍值进行舍入。

  1. Math.ceil
  2. Math.floor
  3. 如果您希望答案4.90625为4,那么您应该使用Math.floor,如果您希望答案4.90625为5,那么您可以使用Math.ceil

    您可以参考以下代码。

         <meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/google_maps_key" /> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
    

答案 11 :(得分:0)

使用double来施放

Math.ceil((double)value)或类似

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

答案 12 :(得分:0)

默认情况下,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


然后我们将第一个等式代入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 ,我们有

{{1}}

我们完成了。希望这会有所帮助。

答案 13 :(得分:0)

我知道这是一个老问题,但是我认为我们有一个更好的方法,该方法使用BigDecimal来避免精度损失。顺便说一句,使用此解决方案,我们可以使用多种舍入和缩放策略。

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

答案 14 :(得分:-3)

int total = (157-1)/32 + 1

或更一般

(a-1)/b +1