¿Cuál es la forma más sencilla de comprobar si dos enteros tienen el mismo signo? ¿Hay algún truco a pequeña escala para hacer esto?¿La forma más simple de verificar si dos enteros tienen el mismo signo?
Respuesta
Aquí está una versión que funciona en C/C++ que no se basa en tamaños enteros o tienen el problema de desbordamiento (es decir, x * y> = 0 no funciona)
bool SameSign(int x, int y)
{
return (x >= 0)^(y < 0);
}
Por supuesto, puede geek y la plantilla:
template <typename valueType>
bool SameSign(typename valueType x, typename valueType y)
{
return (x >= 0)^(y < 0);
}
Nota: Puesto que estamos utilizando exclusivo o, queremos que el LHS y el RHS a ser diferentes cuando los signos son iguales, por lo tanto los diferentes cheque contra cero.
si (x * y)> 0 ...
suponiendo que no sea cero y tal.
Justo al lado de la parte superior de mi cabeza ...
int mask = 1 << 31;
(a & mask)^(b & mask) < 0;
sólo funciona durante 32 bits enteros, que no estaba estipulado en la pregunta –
si (a * b < 0) signo es diferente, signo demás es igual (o A o B es cero)
No funciona para el desbordamiento –
suponiendo 32 ints bits:
bool same = ((x^y) >> 31) != 1;
poco más concisa:
bool same = !((x^y) >> 31);
Esos dos ejemplos de código deben SIEMPRE SIEMPRE SIEMPRE estar precedidos de un comentario por favor código (en la vida real) –
Oh, por supuesto . En la vida real, probablemente usaría algo como same = Math.Sign (x) == Math.Sign (y). Acabo de dar soluciones diabólicas cuando las personas las piden. : D – Patrick
Um, este código no es válido ... ¿cómo esperas que '& >>' funcione? –
Recordando a 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?
Supongo que esto es más bien dependiente de la máquina, sin embargo.
(entero1 * entero2)> 0
Porque cuando dos enteros comparten un signo, el resultado de la multiplicación siempre será positivo.
También puede hacerlo> = 0 si desea tratar 0 como si fuera el mismo signo pase lo que pase.
Solo funciona hasta que el producto se desborda. – Frosty
también, la multiplicación puede ser bastante lenta ... –
Si uno de los enteros es 0, entonces tienes un problema. – TatiOverflow
int same_sign =! ((X >> 31)^(y >> 31));
si (same_sign) ... otra cosa ...
Como nota técnica, soluciones de bits twiddly van a ser mucho más eficiente que la multiplicación, incluso en arquitecturas modernas. Es sólo alrededor de 3 ciclos que usted está ahorrando, pero ya sabes lo que dicen de un "centavo ahorrado" ...
un centavo ahorrado es la raíz de todo mal, digamos alrededor del 97% del tiempo? – ysth
(a^b) >= 0
evaluará a 1 si el signo es el mismo, 0 en caso contrario.
¡Oh, bien! :-) Me sorprende que me haya perdido esta. Lo realmente bueno de esta solución es que no depende de una cardinalidad de bit particular en la representación entera subyacente. –
Este da como resultado el encantador y compacto "xorl% edi,% esi; sets% al" en x86, solo 6 bytes y dos instrucciones. También es un estudio de caso interesante, ya que es un caso concreto en el que devolver un 'bool' en lugar de un int produce un código dramáticamente mejor. –
@JohnMeacham: preguntándose a qué se refiere con 'es un caso concreto en el que devolver un' bool 'en lugar de un int produce un código dramáticamente mejor' –
Sería cauteloso con cualquier trucos de bit a bit para determinar el signo de los enteros, ya que entonces tiene que hacer suposiciones sobre cómo esos números se representan internamente.
Casi el 100% del tiempo, los enteros se almacenarán como two's compliment, 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 dos complementos, puede verificar el último bit (el extremo izquierdo) en el número entero para determinar si es negativo, por lo que puede 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, solo usaría la función de signo del idioma elegido. Es poco probable que haya problemas de rendimiento con un cálculo como este.
Para cualquier tamaño de int con la aritmética de complemento a dos:
#define SIGNBIT (~((unsigned int)-1 >> 1))
if ((x & SIGNBIT) == (y & SIGNBIT))
// signs are the same
asumiendo 32 bits
if (((x^y) & 0x80000000) == 0)
... la respuesta si (x * y> 0) es malo debido al desbordamiento
No estoy muy seguro de que consideraría "truco bitwise" y "más simple" también. Veo muchas respuestas que están asumiendo números enteros de 32 bits (aunque sería sería una tontería pedir sin firmar); No estoy seguro de que se apliquen a los valores de coma flotante.
Parece que el control "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, se obtiene falso. Si los signos son los mismos, te haces verdadero.
falso && false == false Me temo que tendrías que hacer la negación de un XOR para hacerlo correcto. –
¿Qué hay de malo en
return ((x<0) == (y<0));
?
Um ... Nada ... Triste que todos perdimos la solución simple. – Torlack
Gran respuesta, la simplicidad es maravillosa. –
¿Qué hay de cero firmado? -0.0 vs cero sin signo 0.0 –
dos en dos Suponiendo que 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 1 ns en un procesador moderno con la optimización.
dos en dosno asumir complementan la aritmética:
inline bool same_sign(int x, int y) {
return (x<0) == (y<0);
}
Esto puede requerir uno o dos instrucciones adicionales y tomar un poco más de tiempo.
Usar la multiplicación es una mala idea porque es vulnerable al desbordamiento.
sucursales C versión:
int sameSign(int a, int b) {
return ~(a^b) & (1<<(sizeof(int)*8-1));
}
C++ plantilla para tipos de enteros:
template <typename T> T sameSign(T a, T b) {
return ~(a^b) & (1<<(sizeof(T)*8-1));
}
mejor manera usando std::signbit como sigue:
std::signbit(firstNumber) == std::signbit(secondNumber);
También soporta otros tipos básicos (double
, float
, char
etc.)
- 1. ¿Manera pitónica de verificar si dos diccionarios tienen el mismo conjunto de claves?
- 2. ver si dos archivos tienen el mismo contenido en Python
- 3. ¿Cómo puedo verificar si múltiples variables tienen el mismo valor?
- 4. Vea si dos objetos tienen el mismo tipo
- 5. ¿La forma más simple de sumar dos listas en Scala?
- 6. La forma más rápida de verificar si existe un objeto
- 7. ¿Cuál es la forma más rápida de verificar si dos Tbitmaps son iguales?
- 8. ¿Cuál es la forma más rápida de verificar si dos números dados son coprime?
- 9. ¿La mejor manera de verificar si dos fechas son el mismo día calendario en Groovy?
- 10. Dos o más módulos web definidos en la configuración tienen el mismo contexto raíz
- 11. ¿Qué sucede cuando dos anotaciones diferentes tienen el mismo nombre?
- 12. Dos clases tienen el mismo nombre de tipo XML "objectFactory"
- 13. ¿Cuál es la forma más eficiente de calcular el mínimo común múltiplo de dos enteros?
- 14. Dos clases tienen el mismo nombre de tipo xml
- 15. IllegalAnnotationException: Dos clases tienen el mismo nombre de tipo XML
- 16. ¿La forma más corta de verificar si una variable contiene un entero positivo usando PHP?
- 17. ¿La forma más simple de recorrer dos NSDates en el iPhone?
- 18. ¿Cómo verificar rápidamente si dos objetos de transferencia de datos tienen las mismas propiedades en C#?
- 19. ¿Cuál es la forma más corta de comparar si dos IEnumerable <T> tienen los mismos elementos en C#?
- 20. ¿Qué sucede si dos objetos diferentes tienen el mismo código hash?
- 21. Cómo verificar si dos fechas no están en el mismo día calendario
- 22. ¿Cómo puedo verificar si un entero con signo es positivo?
- 23. La forma más rápida de verificar si el punto extremo WCF está escuchando
- 24. MySQL - La forma más rápida de verificar si los datos en la tabla InnoDB han cambiado
- 25. ¿Cómo saber si dos palabras tienen la misma base?
- 26. ¿Hay alguna manera de verificar si dos objetos tienen alias en Java?
- 27. Método más simple/más eficiente de anidar si ... ¿otro flujo?
- 28. Compruebe si dos variables tienen valores de dos conjuntos diferentes, el modo DRY
- 29. ¿Cómo calculo la similitud de dos enteros?
- 30. ¿La forma más rápida de compilar una aplicación Symbian simple?
Muy bien, el hacker C/C++ en mí es totalmente compatible con este fragmento de código. El ingeniero de software en mí pregunta por qué el usuario necesita saber esto de una manera tan genérica. – user7116
¿Esto no falla si x = 0 e y> 0? –