126
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?

senseiwu
  • 5,001
  • 5
  • 26
  • 47
tom
  • 1,277
  • 2
  • 9
  • 3

15 Answers15

236

You are doing 157/32 which is dividing two integers with each other, which always result in a rounded down integer. Therefore the (int) Math.ceil(...) isn't doing anything. There are three possible solutions to achieve what you want. I recommend using either option 1 or option 2. Please do NOT use option 0.

Option 0

Convert a and b to a double, and you can use the division and Math.ceil as you wanted it to work. However I strongly discourage the use of this approach, because double division can be imprecise. To read more about imprecision of doubles see this question.

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

Option 1

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

You do a / b with always floor if a and b are both integers. Then you have an inline if-statement which checks whether or not you should ceil instead of floor. So +1 or +0, if there is a remainder with the division you need +1. a % b == 0 checks for the remainder.

Option 2

This option is very short, but maybe for some less intuitive. I think this less intuitive approach would be faster than the double division and comparison approach:
Please note that this doesn't work for b < 0.

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

To reduce the chance of overflow you could use the following. However please note that it doesn't work for a = 0 and b < 1.

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

Explanation behind the "less intuitive approach"

Since dividing two integers in Java (and most other programming languages) will always floor the result. So:

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

But we don't want floor(a/b), but ceil(a/b), and using the definitions and plots from Wikipedia: enter image description here

With these plots of the floor and ceil functions, you can see the relationship.

Floor function Ceil function

You can see that floor(x) <= ceil(x). We need floor(x + s) = ceil(x). So we need to find s. If we take 1/2 <= s < 1 it will be just right (try some numbers and you will see it does, I find it hard myself to prove this). And 1/2 <= (b-1) / b < 1, so

ceil(a/b) = floor(a/b + s)
          = floor(a/b + (b-1)/b)
          = floor( (a+b-1)/b) )

This is not a real proof, but I hope you're satisfied with it. If someone can explain it better I would appreciate it too. Maybe ask it on MathOverflow.

mtpc1486
  • 43
  • 1
  • 5
martijnn2008
  • 3,552
  • 5
  • 30
  • 40
  • 1
    It will be a huge favour if you could explain the intuition behind the less intuitive approach? I know this is correct, I want to know how you got to it, and how can I mathematically show it is correct. I tried solving it mathematically, wasn't convinced. – Saad Rehman Shah Apr 20 '14 at 11:40
  • I hope you are satisfied with my edit, I can't do any better I think :( – martijnn2008 Apr 20 '14 at 15:39
  • I assume Math.floor and ceil are only correct for integer division not for long division when values are casted to doubles. Counter examples are 4611686018427386880 / 4611686018427387137 fails on floor and 4611686018427386881 / 4611686018427386880 fails on ceil – Wouter Jul 11 '16 at 12:20
  • My computer prints `0.0` for `Math.floor( (double) a / (double) b)` where `long a = 4611686018427386880L; long b = 4611686018427387137L;` So I guess I misunderstand your question. – martijnn2008 Jul 11 '16 at 21:34
  • I used the wrong value: 4611686018427387137 should be 4611686018427386881 So how to be sure that both math.floor and ceil work for all possible integer values? (One would better depend on integer arithmetic, which is also faster.) – Wouter Jul 16 '16 at 20:29
  • 2
    A point of clarification: The results of option 2's two sub-options are not identical in all cases. A value of zero for a will provide 0 in the first, and 1 in the second (which is not the correct answer for most applications). – Sushisource Aug 10 '16 at 23:31
  • Good catch! I will improve my answer. – martijnn2008 Aug 11 '16 at 08:20
  • 1
    Are you sure you didn't mean "However please note that it doesn't work for a = 0 and b **<** 1" – dantiston Feb 22 '17 at 19:23
  • option 1 lack parentheses in `(a % b == 0) ? 0 : 1` part, otherwise you have incompatible types for `+` operation – Anton Khodak Sep 14 '17 at 07:34
  • @gok "because double division can be imprecise", see questions like [this](https://stackoverflow.com/questions/10444350/c-sharp-loss-of-precision-when-dividing-doubles). – martijnn2008 Nov 27 '17 at 21:19
  • You mention that `floor(x + s) = ceil(x)` is right for any `1/2 <= s < 1` but that is wrong, since `0 = floor(0.75) != ceil(0.25) = 1`. The range is correct for `round(x+s) = ceil(x)`. The solution is still wright but the reason is that `0 <= a % b <= b-1`. Given `floor(a/b) = (a - (a%b)) / b` it's just a rewriting of Option 1. – Radagast81 Sep 25 '19 at 11:04
62

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.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Are you sure int/int will always result in an int?! can you please give source to that?! –  Sep 23 '13 at 06:54
  • 5
    @user1545072: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.2 – Kirby Sep 03 '14 at 22:46
37

157/32 is an integer division because all numerical literals are integers unless otherwise specified with a suffix (d for double l for long)

the division is rounded down (to 4) before it is converted to a double (4.0) which is then rounded up (to 4.0)

if you use a variables you can avoid that

double a1=157;
double a2=32;
int total = (int) Math.ceil(a1/a2);
ratchet freak
  • 47,288
  • 5
  • 68
  • 106
27
int total = (int) Math.ceil((double)157/32);
Phoebus
  • 661
  • 6
  • 16
12

Nobody has mentioned the most intuitive:

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

This solution fixes the double division imprecision.

I.G. Pascual
  • 5,818
  • 5
  • 42
  • 58
4

In Java adding a .0 will make it a double...

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

When dividing two integers, e.g.,

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

the result is an int, the value of which is a divided by b, rounded toward zero. Because the result is already rounded, ceil() doesn't do anything. Note that this rounding is not the same as floor(), which rounds towards negative infinity. So, 3/2 equals 1 (and floor(1.5) equals 1.0, but (-3)/2 equals -1 (but floor(-1.5) equals -2.0).

This is significant because if a/b were always the same as floor(a / (double) b), then you could just implement ceil() of a/b as -( (-a) / b).

The suggestion of getting ceil(a/b) from

int n = (a + b - 1) / b;, which is equivalent to a / b + (b - 1) / b, or (a - 1) / b + 1

works because ceil(a/b) is always one greater than floor(a/b), except when a/b is a whole number. So, you want to bump it to (or past) the next whole number, unless a/b is a whole number. Adding 1 - 1 / b will do this. For whole numbers, it won't quite push them up to the next whole number. For everything else, it will.

Yikes. Hopefully that makes sense. I'm sure there's a more mathematically elegant way to explain it.

jorgenman
  • 81
  • 2
2

Also to convert a number from integer to real number you can add a dot:

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

And the result of (157/32.) will be real too. ;)

Vitaliy Borisok
  • 822
  • 3
  • 11
  • 21
2
int total = (int) Math.ceil( (double)157/ (double) 32);
om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
stones333
  • 8,588
  • 1
  • 25
  • 27
1

Check the solution below for your question:

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

Here you should multiply Numerator with 1.0, then it will give your answer.

int total = (int) Math.ceil(157*1.0/32);
Un known
  • 11
  • 2
0

Use double to cast like

Math.ceil((double)value) or like

Math.ceil((double)value1/(double)value2);
Bhupinder
  • 1,329
  • 1
  • 14
  • 29
0

Java provides only floor division / by default. But we can write ceiling in terms of floor. Let's see:

Any integer y can be written with the form y == q*k+r. According to the definition of floor division (here floor) which rounds off r,

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

and of ceiling division (here ceil) which rounds up r₁,

ceil(q*k+r₁, k) == q+1  , where 1 ≤ r₁ ≤ k

where we can substitute r+1 for r₁:

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


Then we substitute the first equation into the third for q getting

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

Finally, given any integer y where y = q*k+r+1 for some q,k,r, we have

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

And we are done. Hope this helps.

ShellayLee
  • 327
  • 2
  • 6
  • I'm sure this is correct, but since the point of this is to clarify, it's not clear to me why `ceil` is defined as such from the intiuitive definition, in particular where we are taking the ceil of an integer, i.e. r1 = k. Since the edge cases are what's tricky about this, I think it needs to be spelled out a bit more. – Luigi Plinge Dec 02 '18 at 14:29
  • @LuigiPlinge To me the derivation cannot be simpler due to the intrinsic difference between floor and ceiling in context of division operation. I think you don't need to focus on the edge case - it's a natural fact when you try to unify the definitions of floor and ceiling via breaking down an integer. As a result, the proof is just three steps, and the conclusion can be roughly remembered as "one amortized step back, then one absolute step forward". – ShellayLee Apr 03 '19 at 20:52
0

There are two methods by which you can round up your double value.

  1. Math.ceil
  2. Math.floor

If you want your answer 4.90625 as 4 then you should use Math.floor and if you want your answer 4.90625 as 5 then you can use 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);

    }

}
Deepak Kumbhar
  • 484
  • 7
  • 17
0

I know this is an old question but in my opinion, we have a better approach which is using BigDecimal to avoid precision loss. By the way, using this solution we have the possibility to use several rounding and scale strategies.

final var dividend = BigDecimal.valueOf(157);
final var divisor = BigDecimal.valueOf(32);
final var result = dividend.divide(divisor, RoundingMode.CEILING).intValue();
-3
int total = (157-1)/32 + 1

or more general

(a-1)/b +1