how to always round up to the next integer [duplicate]
i am trying to find total pages in building a pager on a website (so i want the result to开发者_JAVA技巧 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 of 1
.
How would I code it so i get 2
in this case (the remainder should always add 1
)
Math.Ceiling((double)list.Count() / 10);
(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
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);
}
}
This will also work:
c = (count - 1) / 10 + 1;
I think the easiest way is to divide two integers and increase by one :
int r = list.Count() / 10;
r += (list.Count() % 10 == 0 ? 0 : 1);
No need of libraries or functions.
edited with the right code.
You can use Math.Ceiling
http://msdn.microsoft.com/en-us/library/system.math.ceiling%28v=VS.100%29.aspx
Xform to double (and back) for a simple ceil?
list.Count()/10 + (list.Count()%10 >0?1:0)
- this bad, div + mod
edit 1st: on a 2n thought that's probably faster (depends on the optimization): div * mul (mul is faster than div and mod)
int c=list.Count()/10;
if (c*10<list.Count()) c++;
edit2 scarpe all. forgot the most natural (adding 9 ensures rounding up for integers)
(list.Count()+9)/10
Check by using mod - if there is a remainder, simply increment the value by one.
精彩评论