2010-04-20 22 views
23

estoy buscando la forma más rápida de hacer una división entera en php. por ejemplo, 5/2 debería ser 2 y 6/2 debería ser 3 y así sucesivamente. si simplemente hago esto, php devolverá 2.5 en el primer caso, la única solución que pude encontrar fue usar intval($my_number/2), que no es tan rápido como quiero (pero da los resultados esperados).división entera en php

¿alguien puede ayudarme con esto?

EDIT:
gracias a todos ustedes por sus ideas, he utilizado la postet guión de rubber_boots para probar algunos de ellos con 10000000 iteraciones, aquí se pueden ver los resultados (MAMP en un 3 o 4 años de edad MacBook con 2 GHz 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 

hasta ahora, desplazamiento de bit es la manera más rápida, pero voy a dejar esta pregunta abierta por un día para ver si hay otras possibilitys de este ...

EDIT2:
actualizado los resultados, añade redonda() con PHP_ROUND_HALF_DOWN (gracias a Col._Shrapnel)

+4

cuánto cálculos Simplemente curioso que participan en el código para hacer que tales una función de rendimiento significativo? –

+8

5/2 debe ser 4? ¿Es eso una cosa php? – nvuono

+0

tengo que hacer unos 2-3 millones de cálculos donde usar el intval() - cosa va a tomar 30-40 segundos (y creo que es posible hacer esto 2 o 3 veces más rápido) – oezi

Respuesta

28

si se trata de la división por 2, la forma más rápida de hacerlo es cambiar de bit.

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

y así sucesivamente. lo que hace es simplemente desplazar los bits a la derecha en 1 bit, dividiendo así el número por 2 y perdiendo el resto

1110 >> 1 = 111 
1011 >> 1 = 101 
1011 >> 2 = 10 //division by 4 
1011 << 1 =10110 
+5

+1 para el enfoque inteligente y para prestar atención en las clases de Arquitectura de Computadora ! – Leonel

+0

¿Qué pasa si no es división por 2? – Pacerier

+0

Luego, solo divide por ese número. La división por un poder de 2 es un caso especial. Y se usa en muchos casos. Por ejemplo, si desea transformar un formato de color HEX en valores RGB, binario es la manera de hacerlo. También he encontrado muchos problemas que tienen soluciones elegantes que usan tales operaciones, que son diez veces más eficientes que los algoritmos que usan aritmética decimal. – AlexanderMP

33

Sólo echarlo a un int:

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

Por alguna razón, es mucho más rápido que intval().

Editar: I Asumo que busca un general solución división entera. De desplazamiento de bits es un caso especial para dividir por (o multiplicar por) potencias de 2. Si esto le interesa a continuación:

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

manera:

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

Pero dos salvedades:

  1. Muchos compiladores/intérpretes harán esto automáticamente, por lo que no tiene sentido adivinarlo;

  2. A menos que esté haciendo esta división al menos 100.000 veces en un solo ejecución de script no moleste. Es una micro-optimización inútil.

estudiar más en detalle (2), sí (int) es más rápido que parseInt() pero qué es importante? Casi seguro que no. Concéntrese en el código legible y un buen algoritmo. Este tipo de cosas es una distracción irrelevante.

+0

eso es muy bueno, pero encontré una solución más rápida mientras tanto, pero muchas gracias por este consejo. – oezi

+1

"Por cualquier razón" => intval() es una función, (int) no lo es. En PHP, las funciones tienen bastante sobrecarga, por eso es más rápido. "Muchos compiladores/intérpretes harán esto automáticamente" => PHP es tonto, no optimiza para usted. Pero estoy totalmente de acuerdo con "Foco en el código legible y un buen algoritmo. Este tipo de cosas es una distracción irrelevante". :) – NikiC

1

la ronda() generalmente se utiliza para tal fin. Pero no tengo idea de su velocidad. Nunca he tenido millones de cálculos en mi código. Solo unas décimas de máximo.

+0

round/ceil/floor son un poco más lentos que intval y roudn da resultados incorrectos (2.5 se convertirá en 3 en lugar de 2) - pero gracias por probar – oezi

+0

@oezi round puede dar los resultados deseados, a cualquiera que pueda leer un algunas líneas del manual. de todos modos es su problema de hardware/problema de diseño de la aplicación, no la función de PHP uno –

+0

bien, mi error, si pasa un tercer parámetro, es posible que letzt round() redondee hacia abajo en ese caso. voy a actualizar los resultados en mi pregunta para considerar esta opción ... – oezi

2

sólo funciona si $ x y $ y son enteros

function int_divide($x, $y) { 
    return ($x - ($x % $y))/$y; 
} 
1

redonda uso() o ceil() o baja() funciones declare lo contrario del tipo antes como int()

+0

como menciono en otro comentario, estas funciones son incluso más lentas que intval() – oezi

4

sólo prueba que:

Resultado (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 

Código:

... 
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); 
... 

Saludos

RBO

5

Je, no sé cómo llegué a esta pregunta, ya que parece ser de 2010 y esto no es realmente una respuesta, pero como el autor parece recoger todas maneras de dividir inegers rápido que puede ayudar a alguien aquí.

Suelo utilizar 0 | en lugar de (int) cuando escribo código rápido para mí, porque "|" el operador tiene preferencia de amante y la mayoría de los demás operadores, por lo que no necesita paréntesis adicionales. Incluso

$x=0| 0.3+0.7; 

funcionará como se espera y se encuentra fácilmente cuando nos fijamos en el código (al menos para mí) como Sólo pienso de "= 0 |" como operador especial "set and cast to int".

lo tanto, para añadir a su colección (estos son simplemente otras formas de emitidos a int):

$c=0| $x/$y; 

y

$c=$x/$y % PHP_INT_MAX; 
+0

wow, gracias. Nunca había escuchado sobre '0 |' antes. Lo agregaré a mi lista cuando esté en casa. – oezi