studio reales proyectos programacion libro introducción incluye herramientas fundamentos fuente español código con avanzado aplicaciones java performance xor

java - reales - La forma más rápida de verificar si dos enteros están en el mismo lado de 0



libro de android studio en español pdf (6)

Los enviaría por bit a int sin signo, y xo el MSB (bit más significativo) - mucho más rápido que cualquier comparación (que hace una resta) o multiplicación

Necesito verificar si dos enteros están en el mismo lado de cero muchas veces. No me importa si es positivo o negativo, solo que es el mismo lado ... y el rendimiento es muy importante.

Actualmente estoy haciendo esto:

if (int1 == 0 || int2 == 0) { // handle zero } else if ((int1 ^ int2) > 0) { // different side } else { // same side }

Esta es una mejora del 30% en la velocidad (probado con caliper ) en comparación con lo más obvio:

if ((int1 > 0 && int2 > 0) || (int1 < 0 && int2 < 0)) {

¿Se puede hacer más rápido?

Si alguien quiere ver el marco de prueba que estoy usando para el 30%, está aquí. Utilicé calibre 0.5-rc1

NOTA: Todas estas soluciones verifican el primer bit, básicamente, que para cero es lo mismo que un número positivo. Entonces, si eso funciona para su aplicación, no necesita hacer una comprobación de cero.

Lista de referencia:

  • XOR: respuesta original con corrección de errores
  • Ifs: Solución obvia ((&&)||(&&))
  • Bits: la solución de @ hatchet (>>31) == (>>31)
  • BitAndXor: la solución de @ greedybuddha (0x80000000)
  • BitAndEquals: la solución de @ greedybuddha modificada para usar == no ^
  • XorShift: la solución de @ aaronman (^)>>31 == 0

Salida de pinza:

0% Scenario{vm=java, trial=0, benchmark=XOR} 1372.83 ns; ?=7.16 ns @ 3 trials 17% Scenario{vm=java, trial=0, benchmark=Ifs} 2397.32 ns; ?=16.81 ns @ 3 trials 33% Scenario{vm=java, trial=0, benchmark=Bits} 1311.75 ns; ?=3.04 ns @ 3 trials 50% Scenario{vm=java, trial=0, benchmark=XorShift} 1231.24 ns; ?=12.11 ns @ 5 trials 67% Scenario{vm=java, trial=0, benchmark=BitAndXor} 1446.60 ns; ?=2.28 ns @ 3 trials 83% Scenario{vm=java, trial=0, benchmark=BitAndEquals} 1492.37 ns; ?=14.62 ns @ 3 trials benchmark us linear runtime XOR 1.37 ================= Ifs 2.40 ============================== Bits 1.31 ================ XorShift 1.23 =============== BitAndXor 1.45 ================== BitAndEquals 1.49 ================== vm: java trial: 0

Parece que @aaronman es el ganador


Otra respuesta ...

final int i = int1 ^ int2; if (i == 0 && int1 == 0) { // both are zero } else if (i & Integer.MIN_VALUE == Integer.MIN_VALUE) { // signs differ } else { // same sign }


Respuestas alternativas

Compara el bit de signo

return ((n >> 31) ^ (n2 >> 31) ) == 0 ? /* same */ : /* different */;

Manera alternativa de comparar bit de signo

return (((int1 & 0x80000000) ^ (int2 & 0x80000000))) == 0 ? /* same */ : /* different */;

y acabo de verificar, pero el código de Op es incorrecto cuando int1 == int2 . Lo siguiente siempre se imprimirá diferente si son lo mismo.

if (int1 == 0 || int2 == 0) { // handle zero } else if ((int1 ^ int2) < 0) { // same side } else { // different side }


(int1 ^ int2) >> 31 == 0 ? /*on same side*/ : /*different side*/ ; Esto no necesariamente maneja 0 correctamente. No estoy seguro de lo que quería hacer en ese caso.
EDITAR: también quería señalar que si esto estuviera en c en lugar de java, podría optimizarse aún más eliminando el == 0 debido a la forma en que los booleanos trabajan en c, aunque los casos se cambiarían


int int1 = 3; int int2 = 4; boolean res = ( (int1 * int2) >= 0) ? true : false; System.out.println(res);


if (int1 == 0 || int2 == 0) { // handle zero } else if ((int1 >> 31) == (int2 >> 31)) { // same side } else { // different side }

o

if (int1 == 0 || int2 == 0) { // handle zero } else if ((int1 & Integer.MIN_VALUE) == (int2 & Integer.MIN_VALUE)) { // same side } else { // different side }

La idea de ambos es la misma: elimine todo menos el bit de signo y, a continuación, compárelo para determinar la igualdad. No estoy seguro de cuál es más rápido, el cambio a la derecha (>>) o al bit y (&).