web-development-kb-es.site

¿La forma más sencilla de verificar si dos enteros tienen el mismo signo?

¿Cuál es la forma más sencilla de verificar si dos enteros tienen el mismo signo? ¿Hay algún truco corto a nivel de bits para hacer esto?

60
Gerber

Aquí hay una versión que funciona en C/C++ que no se basa en tamaños de enteros o tiene el problema de desbordamiento (es decir, x * y> = 0 no funciona)

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

Por supuesto, puedes geek out y la plantilla:

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

Nota: Ya que estamos utilizando exclusivo o, queremos que el LHS y el RHS sean diferentes cuando los signos sean los mismos, por lo tanto, el cheque diferente contra cero.

47
Torlack

Qué hay de malo en

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

?

202
Rik
(a ^ b) >= 0

evaluará a 1 si el signo es el mismo, 0 en caso contrario.

23
Chris Jobson

Sería cauteloso con cualquier truco a nivel de bits para determinar el signo de los enteros, ya que entonces hay que hacer suposiciones sobre cómo se representan internamente esos números.

Casi el 100% del tiempo, los enteros se almacenarán como cumplido de dos , pero no es una buena práctica hacer suposiciones sobre las partes internas de un sistema a menos que esté usando un tipo de datos que garantice un formato de almacenamiento particular.

Como complemento a dos, solo puede marcar el último bit (el más a la izquierda) en el entero para determinar si es negativo, por lo que puede comparar solo estos dos bits. Esto significaría que 0 tendría el mismo signo como un número positivo, lo cual está en desacuerdo con la función de signo implementada en la mayoría de los idiomas.

Personalmente, solo uso la función de signo de su idioma elegido. Es poco probable que haya problemas de rendimiento con un cálculo como este.

12
SpoonMeiser

Suponiendo 32 bits bit:

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

Un poco más terso:

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

No estoy realmente seguro de considerar "truco a nivel de bits" y "más simple". Veo muchas respuestas que asumen enteros de 32 bits con signo (aunque sería sería una tontería pedir un signo sin signo); No estoy seguro de que se apliquen a valores de punto flotante.

Parece que la verificación "más simple" sería comparar cómo ambos valores se comparan con 0; esto es bastante genérico asumiendo que los tipos pueden ser comparados:

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

Si los signos son opuestos, obtienes falso. Si los signos son los mismos, obtienes verdad.

5
OwenP

(integer1 * integer2)> 0

Porque cuando dos enteros comparten un signo, el resultado de la multiplicación siempre será positivo.

También puede hacerlo> = 0 si quiere tratar a 0 como si fuera el mismo signo sin importar qué.

4
Benjamin Autin

Suponiendo que la aritmética se complementa con dos ( http://en.wikipedia.org/wiki/Two_complement ):

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

Esto puede tomar tan poco como dos instrucciones y menos de 1 ns en un procesador moderno con optimización.

No asumiendo dos aritmética complementaria:

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

Esto puede requerir una o dos instrucciones adicionales y demorar un poco más.

Usar la multiplicación es una mala idea porque es vulnerable al desbordamiento.

4
user10315

si (x * y)> 0 ...

suponiendo que no es cero y tal.

3
Yes - that Jake.

Como nota técnica, las soluciones de bit twiddly serán mucho más eficientes que la multiplicación, incluso en arquitecturas modernas. Está ahorrando solo 3 ciclos, pero ya sabe lo que dicen sobre un "centavo ahorrado" ...

2
Daniel Spiewak

versión sin sucursales en C:

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

Plantilla de C++ para tipos enteros:

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

Justo al lado de la parte superior de mi cabeza...

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

Para cualquier tamaño de int con aritmética de complemento a dos:

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

suponiendo 32 bits

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

... la respuesta if(x*y>0) es mala debido al desbordamiento

1
ugasoft

si el signo (a * b <0) es diferente, el signo de lo contrario es el mismo (o a o b es cero)

0
dogfish

Pensando en mis días de universidad, en la mayoría de las representaciones de máquinas, ¿no es el bit más a la izquierda de un número entero a 1 cuando el número es negativo, y 0 cuando es positivo?

Sin embargo, me imagino que esto depende de la máquina.

0
Dana

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

if (same_sign) ... else ...

0
andrew

Mejor manera de usar std :: signbit de la siguiente manera:

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

También es compatible con otros tipos básicos (double, float, char etc).

0
ashiquzzaman33