2008-09-15 6 views

ответ

42

Вот версия, которая работает в C/C++, который не зависит от размеров целочисленных или имеют проблему переполнения (т.е. х * у> = 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

если (х * у)> 0 ...

предполагая ненулевой и такие.

1

Только от верхней части моей головы ...

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

работает только для 32-битных целых чисел, которые не предусмотренных в вопросе – 2009-08-17 00:10:26

0

если (а * Ь < 0) знак отличается, другой знак же (или или б равен нулю)

+0

Не работает для перелива – 2009-08-17 00:11:33

6

Предполагая, что 32 бит Интс:

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

Слегка более лаконична:

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

Эти два примера кода должны ВСЕГДА ВСЕГДА ВСЕГДА предшествует код комментарий, пожалуйста (в реальной жизни) – 2008-09-15 21:08:20

+3

О, конечно , В реальной жизни я, вероятно, использовал бы что-то вроде этого = Math.Sign (x) == Math.Sign (y). Я просто даю злые битвидические решения, когда люди просят их. : D – Patrick 2008-09-15 23:00:30

+1

Ум, это недопустимый код ... как вы ожидаете `& >>` работать? – 2017-10-04 01:30:39

0

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

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

4

(integer1 * integer2)> 0

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

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

+2

Работает только до тех пор, пока продукт не переполнится. – Frosty 2008-09-18 20:55:09

+1

также, умножение может быть довольно медленным ... – 2009-08-16 18:05:31

+0

Если одно из целых чисел равно 0, то у вас есть проблема. – TatiOverflow 2016-12-10 10:18:51

0

int same_sign =! ((X >> 31)^(y >> 31));

если (same_sign) ... еще ...

2

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

+5

спасенная копейка - корень всего зла, скажем, около 97% времени? – ysth 2009-08-16 18:54:21

18
(a^b) >= 0 

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

11

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

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

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

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

1

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

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

предполагая 32 бит

если (((х^у) & 0x80000000) == 0)

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

5

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

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

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

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

187

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

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

?

4

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

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

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

не предполагающие двойки дополнение арифметика:

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

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

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

1

внеофисный версия C:

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

C++ шаблон для целочисленных типов:

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

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

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

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