tienen suman suma signo resueltos resta representan racionales que propiedades operaciones números numeros mismo los igual historia enteros ejercicios ejemplos diferente cómo conjunto con como integer bit-manipulation sign

integer - suman - suma de numeros enteros con diferente signo wikipedia



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

(integer1 * integer2)> 0

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

También puede hacer que> = 0 si desea tratar 0 como el mismo signo pase lo que pase.

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


Aquí hay una versión que funciona en C / C ++ que no depende de tamaños 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 y plantilla:

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

Nota: Dado que estamos usando exclusivo o, queremos que el LHS y el RHS sean diferentes cuando los signos son iguales, por lo tanto, la verificación diferente contra cero.


Como nota técnica, las soluciones de poco tiempo van a ser mucho más eficientes que la multiplicación, incluso en las arquitecturas modernas. Solo ahorras 3 ciclos, pero sabes lo que dicen sobre un "centavo ahorrado" ...


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

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


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

Sin embargo, imagino que esto es bastante dependiente de la máquina.


Sería cauteloso con los trucos de bit a bit para determinar el signo de los enteros, ya que entonces tienes que hacer suposiciones sobre cómo esos números están representados internamente.

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

En el cumplido de las dos, puedes simplemente verificar el último bit (el extremo izquierdo) en el entero para determinar si es negativo, por lo que puedes comparar solo estos dos bits. Sin embargo, esto significaría que 0 tendría el mismo signo que un número positivo, lo que está en desacuerdo con la función de signo implementada en la mayoría de los idiomas.

Personalmente, usaría la función de signo del idioma elegido. Es poco probable que haya problemas de rendimiento con un cálculo como este.


asumiendo 32 bits

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

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


if (x * y)> 0 ...

asumiendo que no es cero y tal.


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

if (same_sign) ... else ...


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


Suponiendo que los dos complementan la aritmética ( 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 1ns en un procesador moderno con optimización.

No asumiendo que los dos complementan la aritmética:

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.


versión C sin sucursales:

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

Plantilla C ++ para tipos enteros:

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


Qué hay de malo en

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

?


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

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

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


Realmente no estoy seguro de que considere "truco a nivel de bit" y "más simple". Veo muchas respuestas que están asumiendo números enteros de 32 bits (aunque sería tonto pedir unsigned); No estoy seguro de que se apliquen a los valores de coma flotante.

Parece que el cheque "más simple" sería comparar cómo ambos valores se comparan con 0; esto es bastante genérico suponiendo que los tipos se pueden comparar:

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

Si los signos son opuestos, obtienes falso. Si los signos son los mismos, te haces verdadero.


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

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


Suponiendo 32 bit ints:

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

Un poco más escueto:

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


(a ^ b) >= 0

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