Подтвердить что ты не робот

Самый быстрый способ проверить, находятся ли два целых числа на одной стороне 0

Мне нужно проверить, много ли целых чисел на одной стороне нуля. Меня не волнует, что это положительный или отрицательный, просто что это одна и та же сторона... и производительность очень важна.

В настоящее время я делаю это:

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

Это 30% -ное улучшение скорости (проверено с caliper) более очевидным:

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

Можно ли сделать это быстрее?

Если кто-то хочет увидеть тестовую структуру, которую я использую для 30%, это здесь. Я использовал суппорт 0.5-rc1

ПРИМЕЧАНИЕ.. Все эти решения проверяют первый бит, в основном, который для нуля совпадает с положительным числом. Поэтому, если это работает для вашего приложения, вам не нужно делать нулевую проверку.

Список контрольных показателей:

  • XOR: Оригинальный ответ с исправлением ошибки
  • Ifs: Очевидное решение ((&&)||(&&))
  • Биты: @hatchet solution (>>31) == (>>31)
  • BitAndXor: решение @greedybuddha (0x80000000)
  • BitAndEquals: решение @greedybuddha изменено для использования == not ^
  • XorShift: решение @aaronman (^)>>31 == 0

Выход суппорта:

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

Похоже, @aaronman - победитель

4b9b3361

Ответ 1

(int1 ^ int2) >> 31 == 0 ? /*on same side*/ : /*different side*/ ; Это не обязательно верно 0, я не уверен, что вы хотели сделать в этом случае.
EDIT: также хотелось бы отметить, что если это было в c вместо java, его можно было бы оптимизировать, избавившись от == 0 из-за того, как boolean работает в c, случаи будут переключаться, хотя

Ответ 2

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

или

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

Идея обоим - одно и то же - разделите все, кроме знакового бита, а затем сравните это для равенства. Я не уверен, что быстрее, правый сдвиг ( → ) или побитовый и (&).

Ответ 3

Я бы разбил их на неподписанные int и xor MSB (наиболее значимый бит) - намного быстрее, чем любое сравнение (которое делает вычитание) или умножение

Ответ 4

Альтернативные ответы

Сравнить бит знака

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

Альтернативный способ сравнения знакового бита

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

и я просто подтвердил, но код Op неправильный, когда int1 == int2. Следующие будут всегда печатать разные, если они одинаковы.

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

Ответ 5

Другой ответ...

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
}

Ответ 6

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

 System.out.println(res);