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

Самый простой способ проверить, имеют ли два целых числа один знак?

Какой самый простой способ проверить, имеют ли два целых числа один знак? Есть ли короткий побитовый трюк, чтобы сделать это?

4b9b3361

Ответ 1

Вот версия, которая работает в C/С++, которая не полагается на целочисленные размеры или имеет проблему переполнения (т.е. x * y >= 0 не работает)

bool SameSign(int x, int y)
{
    return (x >= 0) ^ (y < 0);
}

Конечно, вы можете выкрикивать и шаблон:

template <typename valueType>
bool SameSign(typename valueType x, typename valueType y)
{
    return (x >= 0) ^ (y < 0);
}

Примечание. Поскольку мы используем эксклюзивную форму, или мы хотим, чтобы LHS и RHS были разными, когда знаки одинаковы, поэтому различная проверка против нуля.

Ответ 2

Что случилось с

return ((x<0) == (y<0));  

?

Ответ 3

(a ^ b) >= 0

будет оценивать значение 1, если знак тот же, 0 в противном случае.

Ответ 4

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

Почти 100% времени, целые числа будут храниться как два комплимента, но не очень хорошая практика делать предположения о внутренних компонентах если вы не используете тип данных, который гарантирует определенный формат хранения.

В двух комплиментах вы можете просто проверить последний (самый левый) бит в целочисленном, чтобы определить, является ли он отрицательным, поэтому вы можете сравнить только эти два бита. Это означало бы, что 0 будет иметь тот же знак, что и положительное число, но это противоречит знаковой функции, реализованной на большинстве языков.

Лично я просто использую функцию знака выбранного вами языка. Маловероятно, что будут какие-либо проблемы с производительностью с такими вычислениями.

Ответ 5

Предполагая 32-битные ints:

bool same = ((x ^ y) >> 31) != 1;

Немного более кратким:

bool same = !((x ^ y) >> 31);

Ответ 6

Я не уверен, что считаю "поразрядным" и "самым простым" синонимом. Я вижу много ответов, предполагающих подписанные 32-битные целые числа (хотя было бы глупо просить без знака); Я не уверен, что они применимы к значениям с плавающей запятой.

Кажется, что "простейшая" проверка заключалась бы в том, чтобы сравнить, как оба значения сравниваются с 0; это довольно общий, предполагая, что типы можно сравнить:

bool compare(T left, T right)
{
    return (left < 0) == (right < 0);
}

Если знаки противоположны, вы становитесь ложными. Если знаки совпадают, вы получите правду.

Ответ 7

(integer1 * integer2) > 0

Потому что, когда два целых числа имеют знак, результат умножения всегда будет положительным.

Вы также можете сделать это >= 0, если вы хотите рассматривать 0 как один и тот же знак независимо от того, что.

Ответ 8

Предполагая арифметику арифметики (http://en.wikipedia.org/wiki/Two_complement):

inline bool same_sign(int x, int y) {
    return (x^y) >= 0;
}

Это может занимать всего две инструкции и меньше 1 нс на современном процессоре с оптимизацией.

Не предполагать арифметику арифметики:

inline bool same_sign(int x, int y) {
    return (x<0) == (y<0);
}

Для этого может потребоваться одна или две дополнительные инструкции и сделать немного больше.

Использование умножения - плохая идея, потому что она уязвима для переполнения.

Ответ 9

if (x * y) > 0...

считая ненулевое и такое.

Ответ 10

Как техническая нота, бит-twiddly решения будут намного эффективнее, чем умножение даже на современных архитектурах. Это всего лишь около трех циклов, которые вы сохраняете, но вы знаете, что они говорят о "спасенной копейке"...

Ответ 11

Просто с головы...

int mask = 1 << 31;
(a & mask) ^ (b & mask) < 0;

Ответ 12

Для любого размера int с двумя арифметическими дополнениями:

#define SIGNBIT (~((unsigned int)-1 >> 1))
if ((x & SIGNBIT) == (y & SIGNBIT))
    // signs are the same

Ответ 13

Предположим, что 32 бит

if (((x ^ y) и 0x80000000) == 0)

... ответ if (x * y > 0) плохо из-за переполнения

Ответ 14

нераспространяемая версия C:

int sameSign(int a, int b) {
    return ~(a^b) & (1<<(sizeof(int)*8-1));
}

Шаблон С++ для целых типов:

template <typename T> T sameSign(T a, T b) {
    return ~(a^b) & (1<<(sizeof(T)*8-1));
}

Ответ 15

если знак (a * b < 0) отличается, иначе знак тот же (или a или b равен нулю)

Ответ 16

Возвращаясь к моим университетским дням, в большинстве представлений машин, это не самый левый бит целого числа a 1, когда число отрицательно, и 0, когда оно положительно?

Я полагаю, что это скорее зависит от машины.

Ответ 17

int same_sign =! ((x → 31) ^ (y → 31));

if (same_sign)... else...

Ответ 18

Лучше использовать std:: signbit следующим образом:

std::signbit(firstNumber) == std::signbit(secondNumber);

Он также поддерживает другие базовые типы (double, float, char и т.д.).