how to always round up to the next integer
Solution 1
Math.Ceiling((double)list.Count() / 10);
Solution 2
(list.Count() + 9) / 10
Everything else here is either overkill or simply wrong (except for bestsss' answer, which is awesome). We do not want the overhead of a function call (Math.Truncate()
, Math.Ceiling()
, etc.) when simple math is enough.
OP's question generalizes (pigeonhole principle) to:
How many boxes do I need to store
x
objects if onlyy
objects fit into each box?
The solution:
- derives from the realization that the last box might be partially empty, and
- is
(x + y - 1) ÷ y
using integer division.
You'll recall from 3rd grade math that integer division is what we're doing when we say 5 ÷ 2 = 2
.
Floating-point division is when we say 5 ÷ 2 = 2.5
, but we don't want that here.
Many programming languages support integer division. In languages derived from C, you get it automatically when you divide int
types (short
, int
, long
, etc.). The remainder/fractional part of any division operation is simply dropped, thus:
5 / 2 == 2
Replacing our original question with x = 5
and y = 2
we have:
How many boxes do I need to store 5 objects if only 2 objects fit into each box?
The answer should now be obvious: 3 boxes
-- the first two boxes hold two objects each and the last box holds one.
(x + y - 1) ÷ y =
(5 + 2 - 1) ÷ 2 =
6 ÷ 2 =
3
So for the original question, x = list.Count()
, y = 10
, which gives the solution using no additional function calls:
(list.Count() + 9) / 10
Solution 3
A proper benchmark or how the number may lie
Following the argument about Math.ceil(value/10d)
and (value+9)/10
I ended up coding a proper non-dead code, non-interpret mode benchmark.
I've been telling that writing micro benchmark is not an easy task. The code below illustrates this:
00:21:40.109 starting up....
00:21:40.140 doubleCeil: 19444599
00:21:40.140 integerCeil: 19444599
00:21:40.140 warming up...
00:21:44.375 warmup doubleCeil: 194445990000
00:21:44.625 warmup integerCeil: 194445990000
00:22:27.437 exec doubleCeil: 1944459900000, elapsed: 42.806s
00:22:29.796 exec integerCeil: 1944459900000, elapsed: 2.363s
The benchmark is in Java since I know well how Hotspot optimizes and ensures it's a fair result. With such results, no statistics, noise or anything can taint it.
Integer ceil is insanely much faster.
The code
package t1;
import java.math.BigDecimal;
import java.util.Random;
public class Div {
static int[] vals;
static long doubleCeil(){
int[] v= vals;
long sum = 0;
for (int i=0;i<v.length;i++){
int value = v[i];
sum+=Math.ceil(value/10d);
}
return sum;
}
static long integerCeil(){
int[] v= vals;
long sum = 0;
for (int i=0;i<v.length;i++){
int value = v[i];
sum+=(value+9)/10;
}
return sum;
}
public static void main(String[] args) {
vals = new int[7000];
Random r= new Random(77);
for (int i = 0; i < vals.length; i++) {
vals[i] = r.nextInt(55555);
}
log("starting up....");
log("doubleCeil: %d", doubleCeil());
log("integerCeil: %d", integerCeil());
log("warming up...");
final int warmupCount = (int) 1e4;
log("warmup doubleCeil: %d", execDoubleCeil(warmupCount));
log("warmup integerCeil: %d", execIntegerCeil(warmupCount));
final int execCount = (int) 1e5;
{
long time = System.nanoTime();
long s = execDoubleCeil(execCount);
long elapsed = System.nanoTime() - time;
log("exec doubleCeil: %d, elapsed: %.3fs", s, BigDecimal.valueOf(elapsed, 9));
}
{
long time = System.nanoTime();
long s = execIntegerCeil(execCount);
long elapsed = System.nanoTime() - time;
log("exec integerCeil: %d, elapsed: %.3fs", s, BigDecimal.valueOf(elapsed, 9));
}
}
static long execDoubleCeil(int count){
long sum = 0;
for(int i=0;i<count;i++){
sum+=doubleCeil();
}
return sum;
}
static long execIntegerCeil(int count){
long sum = 0;
for(int i=0;i<count;i++){
sum+=integerCeil();
}
return sum;
}
static void log(String msg, Object... params){
String s = params.length>0?String.format(msg, params):msg;
System.out.printf("%tH:%<tM:%<tS.%<tL %s%n", new Long(System.currentTimeMillis()), s);
}
}
Solution 4
This will also work:
c = (count - 1) / 10 + 1;
Solution 5
You can use Math.Ceiling
http://msdn.microsoft.com/en-us/library/system.math.ceiling%28v=VS.100%29.aspx
leora
Updated on June 22, 2020Comments
-
leora almost 4 years
i am trying to find total pages in building a pager on a website (so i want the result to be an integer. i get a list of records and i want to split into 10 per page (the page count)
when i do this:
list.Count() / 10
or
list.Count() / (decimal)10
and the
list.Count() =12
, i get a result of1
.How would I code it so i get
2
in this case (the remainder should always add1
) -
bestsss about 13 yearsconverting int to floating point is just bad (and slow) for such a simple operation
-
bestsss about 13 yearsthat doesn't work correctly when count % 10 ==0. i.e. returns 2 for 10
-
par about 13 yearsNot correct if list.Count() == 10 prior to the division. Then you get 2 when 1 is correct.
-
Rob about 13 yearsIt's not converting from int to floating point, it's telling the function whether the value is a
decimal
or adouble
, as the type cannot be determined automatically. -
Radoslav Georgiev about 13 yearsOops, missed that. You're right guys :)
-
par about 13 yearsThe you have to do mod followed by a test followed by an increment (which is an add and a store). Too expensive. It's easier to do add then divide only (as expensive as mod). No test required.
-
bestsss about 13 years@Rob, you do.. twice, int->floating point(double)->int. it requires double flush of the CPU, the solution is the worst possible correct (for int but not long) one
-
Rob about 13 yearsThe difference in execution times for 1 million cycles is 0.01ms. I think the extra readability for such a negligible increase in processing time is worth it.
-
par about 13 years@Rob - The difference is not simply in the floating point conversion, you also have additional function call overhead for the call to Ceiling(). This isn't "extra readability" it's "extra work" and is not the right way to do this. This question gets asked in myriad ways over and over again on SO and there is a better solution that involves no typecasting and no additional functional call. New programmers need to learn to do it the right way. It turns out doing it correctly is quite readable and seeing someone do it wrong calls all of their code into question.
-
bestsss about 13 years@Rob, you sure all your code was not dead code eliminated? Do you know how to write proper micro-benchmark (almost all developers don't know, so it's a fair question)
-
par about 13 yearsI'll point out also that your solution requires Math.Ceiling() to be available. The solution utilizing knowledge of basic integer math is completely portable.
-
Rob about 13 years@bestsss Yes, I'm sure the it was not dead-code eliminated.
-
bestsss about 13 years@Rob, I've got some free time and decided to hook on the miraculous benchmark of your and wrote my own. Having some HUGE differences between the tests. I write another answer just for the benchmark
-
bestsss about 13 years@par, Added some benchmark results...
-
par about 13 yearsGreat answer. Assertions are one thing, proof is something else entirely.
-
JDandChips almost 11 yearsgood point, proof is something else
-
Ondrej Petrzilka over 10 yearsI like this most, very nice
-
Rumplin about 10 yearsI see multiple problems with your code, especially with numbers like 0 and 20(would return 3) or any larger number than 10.
-
Saurabh about 10 years@Rumplin, you are right about 0, but for 20 it returns 2 as expected.
-
Rumplin about 10 yearsYou are right, it works ok for number > 0
-
Andreas over 9 yearsThis is how: Math.Round(8.28, 0, MidpointRounding.AwayFromZero)
-
Julian over 9 yearsEither this is wrong, or the following statement is false: 113 + 4 / 5 = 23,4
-
par over 9 yearsYour statement is false (it's actually 23, which is what we want). See my revised answer.
-
Co7e over 9 yearsA nice solution, but IMO this is less readable than using Math.Ceiling. At a glance it is not clear what the code is meant to be doing.
-
voho over 8 yearsgenerally: (count + pageSize - 1) / pageSize
-
Efran Cobisi over 8 yearsInstead of rounding the quotient to next whole integer, I believe you should pick its integer part instead:
Math.Truncate((decimal)((list.Count() + 9 ) / 10))
-
par over 8 years@EfranCobisi You're correct in principle, but picking the integer part happens automatically here (follow the integer division link in my answer to see why), so a call to
Math.Truncate()
is not only redundant, it adds computational overhead we want to explicitly avoid. -
Neil Thompson over 7 yearsgreat explanation
-
ZX9 over 7 yearsWhy this answer has not been more recognized is beyond me. This is by far the most elegant solution.
-
ZX9 over 7 years@Andreas Using Math.Round will also require unnecessary conversion to double.
-
Michael Puckett II about 7 yearsThese guys are complaining about benchmarks for a paging formula... Rob's answer is best man. It's clean and simple and you're not processing this hundreds of times in some iteration... Once you have a list you simply need to know the number of pages, this type conversion fuss from int to double to int is for nanoseconds of time that will add up to a possible split second one day. Not worth the time to even write this comment in response honestly. Sometimes even milliseconds added here or there is worth simplicity.
-
Neil almost 6 years@Co7e you could add a comment. Efficiency is more valuable imo.
-
mr5 over 5 years113 + 4 / 5 is actually 113.8 or 114
-
par over 5 years@mr5 Is correct that parentheses definitely matter here.
113 + 4 / 5
when written without parentheses is interpreted as113 + (4 / 5)
by the compiler, and equals either 113.8 when using floating point types or 113 when integer types are used (because4 / 5 == 0
with integer division). The original comment should have been written as(113 + 4) / 5
, which is 23.4 with floating point types or 23 with integer types. -
Dimitris Thomas over 3 yearsyou are right, simple math is enough for this problem. Thanks for the answer, worked like a charm for my case as well