tags:

views:

289

answers:

7

r, a and b are integers.

I need the cheapest computation since in a critical part of the code. I found :

r = (a / b) + (((a % b) != 0) ? 1 : 0);

if b is a power of 2, then a / b can be replaced with a >> log2(b)

and a % b with a & (b-1) which should save a lot of computation time.

Do you know any better solution ?

A: 

This may or may not be suitable for what you're looking for, but most (if not all) languages provide access to a mathematical ceiling function. For example, in C#, writing Math.Ceiling(5/2) yields 3.

Adam Robinson
well, the function is Math.Ceiling for one... My guess is he's trying to keep it to integer division, but who knows...
LorenVS
even javascript has it :-) "Math.ceil(5/2)"
Joshua
Floating point math is usually slower than integer, especially if the parameters are integers and need to be converted.
Mark Ransom
+5  A: 

In the title you ask about the "simplest" - yet the question alludes to the most "effective". Which one do you need? In practice the simplest doesn't always equate to the most effective.

So if you need the simplest method, you should probably be using your language's ceiling function (usually called ceil), if you need the most efficient - that really depends a lot on the processor you're using (whether it implements division in hardware and other such factors)

Also, I'm a little skeptical about the performance of log2 - but I may be wrong.. However one thing is pretty clear: optimizing for the sake of optimizing is almost always not a good idea.

Miky Dinescu
In this case the optimization (as Daniel showed) is also clearer code.
Nosredna
Indeed, the most effective is not always the simplest,and log2 is definitely NOT an efficient function (actually b is a constant in my specific case)But you did not play this little game ;-)
dilig0
BTW, "effective" does not mean "efficient". It only means something that works (something that produces a notable effect).
ShreevatsaR
A: 

If you are on a desktop, try floating point numbers and round them. But I doubt that you can find anything that is more cheap than two int devisions plus an add.

The only other option is the DIVMOD operator which some CPUs support. It will give you both the division and the rest in a single call.

Aaron Digulla
+1  A: 

modulo can be implemented a % n = a - (n * (a / n);

So taking that into account you could re-write as

const int div = a / b;
r = div + (((a - (n * div)) != 0) ? 1 : 0 );

which will be marginally faster as you only do one div instead of 2.

Edit: If b is a constant then you can actually remove the divide completely and replace it with a multiply by a "magic number" (relevant to the constant divisor) that will be a small amount faster again. Then again the compiler WILL make this optimisation anyway with a constant divisor.

Goz
It might be marginally faster. With a decent compiler, on a processor with an integer division op that calculates quotient and remainder, only one div will be done either way.
Steve Jessop
Man...better have a good comment in your code when you drop those lines in!
Beska
I was thinking something similar. Some algorithms compute both "/" and "%" at the same time.
Nosredna
Come to think of it, in cases with a "good" division op, this might end up slower than the questioner's code, because it introduces a multiply.
Steve Jessop
Finally someone who wants to play :)All the other ones skipped that contest ;-)I will wait a bit for someone giving a better solution, but your answer is the best candidate for being accepted.
dilig0
What are you talking about dilig0?
Nosredna
Dilig0: have you checked the top rated answer? I appreciate Goz's work here, but the top rated answer is less code and faster.
Beska
@dilig0: yep, "play" what? StackOverflow is a not a programming contest site.
Daniel
Beska has a great point. I wrote my response while my wife was waiting for me outside the office. I didn't really think about the problem. Sure I've given a good optimisation for the modulo operation but Daniel's suggestion is an algorithmic optimisation that makes my minor speed up (as pointed out, provided the compiler doesn't spot it anyway) pale into insiginifance.
Goz
+29  A: 
val r = (a + b - 1) / b

For example:

scala> for(a <- 1 to 10; b <- 1 to a) println("a: "+a+"\tb: "+b+"\tr: "+((a+b-1)/b))
a: 1    b: 1    r: 1
a: 2    b: 1    r: 2
a: 2    b: 2    r: 1
a: 3    b: 1    r: 3
a: 3    b: 2    r: 2
a: 3    b: 3    r: 1
a: 4    b: 1    r: 4
a: 4    b: 2    r: 2
a: 4    b: 3    r: 2
a: 4    b: 4    r: 1
a: 5    b: 1    r: 5
a: 5    b: 2    r: 3
a: 5    b: 3    r: 2
a: 5    b: 4    r: 2
a: 5    b: 5    r: 1
a: 6    b: 1    r: 6
a: 6    b: 2    r: 3
a: 6    b: 3    r: 2
a: 6    b: 4    r: 2
a: 6    b: 5    r: 2
a: 6    b: 6    r: 1
a: 7    b: 1    r: 7
a: 7    b: 2    r: 4
a: 7    b: 3    r: 3
a: 7    b: 4    r: 2
a: 7    b: 5    r: 2
a: 7    b: 6    r: 2
a: 7    b: 7    r: 1
a: 8    b: 1    r: 8
a: 8    b: 2    r: 4
a: 8    b: 3    r: 3
a: 8    b: 4    r: 2
a: 8    b: 5    r: 2
a: 8    b: 6    r: 2
a: 8    b: 7    r: 2
a: 8    b: 8    r: 1
a: 9    b: 1    r: 9
a: 9    b: 2    r: 5
a: 9    b: 3    r: 3
a: 9    b: 4    r: 3
a: 9    b: 5    r: 2
a: 9    b: 6    r: 2
a: 9    b: 7    r: 2
a: 9    b: 8    r: 2
a: 9    b: 9    r: 1
a: 10   b: 1    r: 10
a: 10   b: 2    r: 5
a: 10   b: 3    r: 4
a: 10   b: 4    r: 3
a: 10   b: 5    r: 2
a: 10   b: 6    r: 2
a: 10   b: 7    r: 2
a: 10   b: 8    r: 2
a: 10   b: 9    r: 2
a: 10   b: 10   r: 1

This does assume a and b are positive. If either are negative, it depends on whether the division is symmetric or floored (modern languages and platforms are symmetric), and the signal of a and b.

If a*b >= 0, then the formula works as given. If the division is symmetric and a*b < 0, then a / b gives the correct answer.

Daniel
Good call, wouldn't have thought of doing it that way
LorenVS
For some reason, I have written this code many, many times. The trick is that `(b - 1) / b` is equal to `0`, so it won't change the result unless `a % b > 0`.
Daniel
Fantastic. Very elegant. I'm impressed.
Beska
and a great demonstration over why improving the algorithm wins over optimising what is there provides such huge wins :)
Goz
To me that's the essence of optimization. You look at the inputs and the outputs and try to find the best way (whatever best may mean in the situation) from _here_ to _there_.
Nosredna
Be aware that this doesn't work for negative numbers, because / usually truncates towards zero.
starblue
@starblue, by "doesn't work," do you mean it behaves differently than the code given in the question?
Nosredna
@Nosredna, no, it really doesn't work for negative numbers.
Daniel
If b is a constant as stated in a comment to one of the other answers, and also a power of 2, then the divide should be converted to a bit shift by any intelligent compiler. I imagine that's the answer to the 'game' that you were looking for?
Mark Ransom
Many thanks Daniel :)
dilig0
+3  A: 

What about:

(a - 1) / b + 1;

Obviously you have to watch yourself if a might be 0 or less. Negative numbers don't necessarily divide the way you expect, it depends on language and implementation.

Steve Jessop
A: 

Since no language was specified, I'm going to write a solution in ANS Forth as well...

: div ( a b -- r)
  FM/MOD     \ a b -- q rest
  IF 1+ THEN \ q rest -- r
;
Daniel