views:

438

answers:

6

hi guys,

i'm looking for the fastest way to do an integer division in php. for example, 5 / 2 schould be 2 | 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) - wich isn't as fast as i want it to be (but gives the expected results).

can anyone help me out with this?

EDIT: tanks to all of you for your ideas, i used the script postet 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
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 possibilitys for this...

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

+6  A: 

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
thats very good, but i found any faster solution in the meantime - but thank you very much for this hint.
oezi
A: 

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.

Col. Shrapnel
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
@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
Col. Shrapnel
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
+1  A: 

Only works if $x and $y are integers

function int_divide($x, $y) {
    return ($x - ($x % $y)) / $y;
}
ghoppe
A: 

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

Karthik
as i mentiones in another comment, this functions are even more slowly than intval()
oezi
+3  A: 

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 
Alexander
+2  A: 

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