how to always round up to the next integer

163,813

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 only y objects fit into each box?

The solution:

  1. derives from the realization that the last box might be partially empty, and
  2. 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

Share:
163,813
leora
Author by

leora

Updated on June 22, 2020

Comments

  • leora
    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 of 1.

    How would I code it so i get 2 in this case (the remainder should always add 1)

  • bestsss
    bestsss about 13 years
    converting int to floating point is just bad (and slow) for such a simple operation
  • bestsss
    bestsss about 13 years
    that doesn't work correctly when count % 10 ==0. i.e. returns 2 for 10
  • par
    par about 13 years
    Not correct if list.Count() == 10 prior to the division. Then you get 2 when 1 is correct.
  • Rob
    Rob about 13 years
    It's not converting from int to floating point, it's telling the function whether the value is a decimal or a double, as the type cannot be determined automatically.
  • Radoslav Georgiev
    Radoslav Georgiev about 13 years
    Oops, missed that. You're right guys :)
  • par
    par about 13 years
    The 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
    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
    Rob about 13 years
    The 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
    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
    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
    par about 13 years
    I'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
    Rob about 13 years
    @bestsss Yes, I'm sure the it was not dead-code eliminated.
  • bestsss
    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
    bestsss about 13 years
    @par, Added some benchmark results...
  • par
    par about 13 years
    Great answer. Assertions are one thing, proof is something else entirely.
  • JDandChips
    JDandChips almost 11 years
    good point, proof is something else
  • Ondrej Petrzilka
    Ondrej Petrzilka over 10 years
    I like this most, very nice
  • Rumplin
    Rumplin about 10 years
    I see multiple problems with your code, especially with numbers like 0 and 20(would return 3) or any larger number than 10.
  • Saurabh
    Saurabh about 10 years
    @Rumplin, you are right about 0, but for 20 it returns 2 as expected.
  • Rumplin
    Rumplin about 10 years
    You are right, it works ok for number > 0
  • Andreas
    Andreas over 9 years
    This is how: Math.Round(8.28, 0, MidpointRounding.AwayFromZero)
  • Julian
    Julian over 9 years
    Either this is wrong, or the following statement is false: 113 + 4 / 5 = 23,4
  • par
    par over 9 years
    Your statement is false (it's actually 23, which is what we want). See my revised answer.
  • Co7e
    Co7e over 9 years
    A 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
    voho over 8 years
    generally: (count + pageSize - 1) / pageSize
  • Efran Cobisi
    Efran Cobisi over 8 years
    Instead 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
    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
    Neil Thompson over 7 years
    great explanation
  • ZX9
    ZX9 over 7 years
    Why this answer has not been more recognized is beyond me. This is by far the most elegant solution.
  • ZX9
    ZX9 over 7 years
    @Andreas Using Math.Round will also require unnecessary conversion to double.
  • Michael Puckett II
    Michael Puckett II about 7 years
    These 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
    Neil almost 6 years
    @Co7e you could add a comment. Efficiency is more valuable imo.
  • mr5
    mr5 over 5 years
    113 + 4 / 5 is actually 113.8 or 114
  • par
    par over 5 years
    @mr5 Is correct that parentheses definitely matter here. 113 + 4 / 5 when written without parentheses is interpreted as 113 + (4 / 5) by the compiler, and equals either 113.8 when using floating point types or 113 when integer types are used (because 4 / 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
    Dimitris Thomas over 3 years
    you are right, simple math is enough for this problem. Thanks for the answer, worked like a charm for my case as well