23

I'm looking for the fastest way to do an integer division in php. for example, 5 / 2 should be 2 and 6 / 2 should be 3 and so on. If I simply do this, php will return 2.5 in the first case, the only solution I could find was using intval($my_number/2) - which isn't as fast as I want it to be (but gives the expected results).

How can I do this?

EDIT:
Thanks to all of you for your ideas, I used the script posted by rubber_boots to test some of them with 10000000 iterations, here you can see the results (MAMP on a 3 or 4 year old MacBook with 2Ghz Intel core 2 duo):

start (10000000)
(int)...: 2.26 sec
floor(): 4.36 sec
int_divide(): 2.86 sec
bit-shift: 1.45 sec //note: only works for divisions through powers of 2
intval(): 4.51 sec
round() with PHP_ROUND_HALF_DOWN: 5.48 sec

until now, bit-shift is the fastest way, but I'll leave this question open for a day to see if there are other possibilities for this...

EDIT2:
updated the results, added round() with PHP_ROUND_HALF_DOWN (thanks to Col._Shrapnel)

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
oezi
  • 51,017
  • 10
  • 98
  • 115
  • 4
    Just curious how much calculations involved in your code to make such a function performance-significant? – Your Common Sense Apr 20 '10 at 09:00
  • 8
    5/2 should be 4? is that a php thing? – nvuono Apr 20 '10 at 09:05
  • i have to do about 2-3 million calculations where using the intval()-thing is going to take 30-40 seconds (and i think its possigble to do this 2 or 3 times faster) – oezi Apr 20 '10 at 09:09
  • if you really want a performance boost, look into writing a COM object (if it's Windows OS), or a PHP plugin in C++, that would divide the whole task into multiple threads, to benefit from the multi-core CPU that a modern server must have. Even without threading it would be much faster if it were a C++ plugin or COM object. – Alex Apr 20 '10 at 09:12
  • 1
    In addition to @Alexander's suggestion, you might also want to consider to use multiple async processes with Gearman or other JobQueues. – Gordon Apr 20 '10 at 09:17
  • 1
    You have a pokey server. Bitshifting is indeed fastest and intval to be avoided, but I did a test on my server (linux/pentium based) with 3 million iterations: $result = intval($x/2) [3.5481s]; $result = (int)(6/2) [1.5452s]; $result = $x>>1 [1.1542s]; result = ($x-($x%2))/2 [1.692s] Unclear why you'd need php performance to be so highly tuned. The fact you answered yourself in about 6 min leads me to suspect this is a bit of a troll question. – ghoppe Apr 20 '10 at 09:38
  • Thanks, @Gordon for the suggestion of Gearman. And it's when I thought that PHP Java Bridge was hot :) – Alex Apr 20 '10 at 09:50
  • I'm getting longer times for intdiv and shorter for intval: bitshift 1.057 (int) 0.5* 1.144 (int) 1.274 intval() 1.318 intdiv() 4.295 floor() 4.389 round(PHP_ROUND_HALF_DOWN) 5.015 – Charon ME Aug 30 '23 at 13:03

7 Answers7

33

Just cast it to an int:

$result = (int)(6 / 2);

For whatever reason, it's much faster than intval().

Edit: I assume you are looking for a general integer division solution. Bit-shifting is a special case for dividing by (or multiplying by) powers of 2. If that interests you then:

a / b^n = a >> n where a, b, n are integers

so:

a / 2 = a / 2^1 = a >> 1

But two caveats:

  1. Many compilers/interpreters will do this for you automatically so there is no point second guessing it;

  2. Unless you're doing this division at least 100,000 times in a single script execution don't bother. It's a pointless micro-optimization.

To further elaborate on (2), yes (int) is faster than parseInt() but does it matter? Almost certainly not. Focus on readable code and a good algorithm. This sort of thing is an irrelevant distraction.

cletus
  • 616,129
  • 168
  • 910
  • 942
  • thats very good, but i found any faster solution in the meantime - but thank you very much for this hint. – oezi Apr 20 '10 at 09:05
  • 1
    "For whatever reason" => intval() is a function, (int) is not. In PHP functions have quite some overhead, that's why it's faster. "Many compilers/interpreters will do this for you automatically" => PHP is dumb, it does not optimize for you. But full agree on "Focus on readable code and a good algorithm. This sort of thing is an irrelevant distraction." :) – NikiC Oct 17 '11 at 14:45
28

if it's division by 2, the fastest way to do it is bit shifting.

5>>1 = 2
6>>1 = 3

and so on and so forth. What it does is just shift the bits to the right by 1 bit, thus dividing the number by 2 and losing the rest

1110 >> 1 =  111
1011 >> 1 =  101
1011 >> 2 =   10 //division by 4
1011 << 1 =10110 
Alex
  • 14,338
  • 5
  • 41
  • 59
  • 5
    +1 for the intelligent approach and for paying attention on the Computer Architecture classes! – Leonel Oct 29 '12 at 07:13
  • What if it's not division by 2? – Pacerier Aug 05 '13 at 18:00
  • Then you just divide by that number. Division by a power of 2 is a special case. And is used in a lot of cases. For example you want to transform a HEX color format into RGB values, binary is the way to do it. I've also encountered many problems which have elegant solutions using such operations, which are tens of times more efficient than algorithms using decimal arithmetic. – Alex Aug 06 '13 at 20:44
  • Thanks, I didn't know it was possible to shift bits in an integer in PHP! @Pacerier: shifting is used to divide by a power of two: to divide by `2^n`, you have to shift `n` bits out of your integer. – Yoone Nov 18 '13 at 07:23
  • @Yoone, no I mean what if we *don't* want to divide by 2. E.g. We want to divide by 5? – Pacerier Nov 18 '13 at 10:55
  • @Pacerier, bit shifting is only used to divide or multiply by `2^n`, because the operation is directly made on the binary value of the integer. If you need to do more complex calculations, you can't use this method, but here's an answer that may lighten you: http://stackoverflow.com/a/18669991/860283 (note that dividing by 5 might be a bit more tricky, because it cannot be written as a sum of `2^n` with `n > 1`) – Yoone Nov 19 '13 at 00:54
5

Heh, I don't know how I got into this question as it seems to be from 2010 and this is not really an answer, but as the author seems to collect all ways to divide inegers fast it may help someone here.

I usually use 0| instead of (int) when I write fast code for myself, because "|" operator have lover precedence then most other operators, so you don't need extra parentheses. Even

$x=0| 0.3+0.7;

will work as expected and it is easily found when you look at code(at least for me) as I just think of "=0|" as special operator "set and cast to int".

So, to add to your collection (these are simply just other ways to cast to int):

$c=0| $x/$y;

and

$c=$x/$y % PHP_INT_MAX;
XzKto
  • 2,472
  • 18
  • 18
  • wow, thanks. i've never heard of `0|` before. i'll add that to my list when i'm at home. – oezi Oct 18 '11 at 14:44
4

Just Test it:

Result (Win32, Core2/E6600):

 generic division (3000000)
 (int)DIV:       1.74 sec
 intval(DIV):    6.90 sec
 floor(DIV):     6.92 sec
 int_divide():   1.85 sec

 division by 2 (3000000)
 (int)(VAL/2):   1.75 sec
 VAL >> 2:       1.63 sec
 (int)(VAL*0.5): 1.72 sec

Code:

 ...
 echo "generic division ($N)\n";
 $start = getTime(); for($i=1; $i<$N; $i++) { $c = (int)(($i+1) / $i); }
 printf("(int)DIV:\t %.2f sec\n", getTime()-$start);

 $start = getTime(); for($i=1; $i<$N; $i++) { $c = intval(($i+1) / $i); }
 printf("intval(DIV):\t %.2f sec\n", getTime()-$start);

 $start = getTime(); for($i=1; $i<$N; $i++) { $c = floor(($i+1) / $i); }
 printf("floor(DIV):\t %.2f sec\n", getTime()-$start);

 $start = getTime(); for($i=1; $i<$N; $i++) { $c = ($i - ($i % ($i+1))) / ($i+1); }
 printf("int_divide():\t %.2f sec\n", getTime()-$start);

 echo "division by 2 ($N)\n";
 $start = getTime(); for($i=1; $i<$N; $i++) { $c = (int)(($i+1) / 2.0); }
 printf("(int)(VAL/2):\t %.2f sec\n", getTime()-$start);

 $start = getTime(); for($i=1; $i<$N; $i++) { $c = ($i+1) >> 2; }
 printf("VAL >> 2:\t %.2f sec\n", getTime()-$start);

 $start = getTime(); for($i=1; $i<$N; $i++) { $c = (int)(($i+1)*0.5); }
 printf("(int)(VAL*0.5):\t %.2f sec\n", getTime()-$start);
 ...

Regards

rbo

rubber boots
  • 14,924
  • 5
  • 33
  • 44
2

Only works if $x and $y are integers

function int_divide($x, $y) {
    return ($x - ($x % $y)) / $y;
}
ghoppe
  • 21,452
  • 3
  • 30
  • 21
1

the round() usually used in such a purpose. But I have no idea of it's speed. I have never had millions of calculations in my code. Merely few tenths max.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • round/ceil/floor are a bit slower than intval and roudn gives wrong results (2.5 will become 3 instead of 2) - but thanks for your try – oezi Apr 20 '10 at 09:06
  • @oezi round can give any desired results, to anyone who can read a few lines from the manual. anyway it's your hardware/poor application design problem, not PHP function one – Your Common Sense Apr 20 '10 at 10:22
  • ok, my fault, if you pass a third parameter it's possible to letzt round() round down in that case. i'll update the results in my question to regard this option... – oezi Apr 20 '10 at 10:52
1

use round() or ceil() or floor() functions otherwise declare the type before like int()

Karthik
  • 3,221
  • 5
  • 28
  • 38
  • as i mentiones in another comment, this functions are even more slowly than intval() – oezi Apr 20 '10 at 09:10