2010-06-08 20 views
7

Quiero poder acceder al bit de signo de un número en C++. Mi código actual es como la siguiente:¿Cómo puedo acceder al bit de signo de un número en C++?

int sign bit = number >> 31; 

Eso parece funcionar, y me da 0 para los números positivos y -1 para los números negativos. Sin embargo, no veo cómo consigo -1 para los números negativos: si 12 es

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1100 

entonces -12 es

1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0011 

y desplazándola 31 bits harían

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 

que es 1, no -1, entonces ¿por qué obtengo -1 cuando lo cambio?

+0

posible duplicado de (http: // stackoverflow. com/questions/141525/absolute-beginners-guide-to-bit-shifting) – msw

+0

int sign_bit = (int) (number> 0); – aviraldg

+5

Para [complemento de dos] (http://en.wikipedia.org/wiki/Two%27s_complement#Complement_of_a_positive_number) (que usan la mayoría de los sistemas modernos), su -12 es incorrecto. Debería terminar 0100. –

Respuesta

11

El resultado del desplazamiento a la derecha de un número negativo en C++ está definido por la implementación. Por lo tanto, nadie sabe qué desplazamiento a la derecha debe tener su -12 en su plataforma específica. Crees que debería hacer lo anterior (1), mientras que digo que puede producir fácilmente un patrón de todo-uno, que es -1. El último se llama cambio de signo extendido. En el cambio de signo extendido, el bit de signo se copia a la derecha, pero nunca se desplaza de su lugar.

Si todo lo que le interesa es el valor del bit de signo, entonces deje de perder tiempo tratando de usar operaciones bit a bit, como desplazamientos, etc. Simplemente compare su número a 0 y vea si es negativo o no.

+1

Esta es una publicación muy antigua, pero acabo de ver esto mientras buscaba otra cosa. Generalmente estoy de acuerdo con lo que dices aquí. Pero hay algunas suposiciones que hizo en su pregunta que podrían haber contribuido al resultado de su código. Esto se puede hacer de forma independiente mediante el cambio de bit o simplemente usando una máscara de bits para verificar el bit de signo. –

+0

Esto no distingue -0.0 de +0.0. Necesitas acceder al bit de signo para eso. Ver la respuesta de John –

+0

@NeilG Según el texto de la pregunta, me parece que estoy preguntando sobre enteros. –

24

¿Qué tal esto?

int sign = number < 0;

2

El operador >> está realizando una arithmetic shift, que conserva el signo del número.

+4

No. El tipo de cambio que realiza el operador '>>' está definido por la implementación. Podría ser cualquier tipo de cambio. – AnT

+0

@AndreyT: Dije "el operador' >> 'está realizando un cambio aritmético", y eso es exactamente lo que está haciendo en este caso, a juzgar por la descripción del OP. Observe que * no * dije "el operador' >> 'siempre realiza un cambio aritmético" o algo por el estilo. Tal vez debería haber sido más explícito, pero de cualquier manera, no creo que mi respuesta merezca un voto negativo. – LukeH

+2

@Downvoters: por favor justifíquense. Expliqué * exactamente * cuál es el problema del OP. No hice ninguna afirmación amplia como "el operador' >> 'siempre realiza un cambio aritmético"; Expliqué * exactamente * qué está haciendo el operador '>>' * en este caso particular *. – LukeH

7

Dado que está cambiando el entero con signo. Emitir el entero a unsigned:

int sign_bit = ((unsigned int)number) >> 31; 
4

Para enteros, pruebe number < 0.

Para números de punto flotante, también puede desear tener en cuenta el hecho de que cero tiene un signo. Es decir, existe un -0.0 que es distinto de +0.0. Para distinguir los dos, desea usar std::signbit.

1
bool signbit(double x) 
{ 
    return 1.0/x != 1.0/fabs(x); 
} 

Mi solución que admite +/- 0.

2

Puede utilizar la biblioteca cmath

#include <cmath> 

y utilizarlo como

std::cout << std::signbit(num); 

Esta función obtener un valor flotante como entrada y un valor booleano como salida.

true for negative 
false for positive 

por ejemplo

std :: cout < < std :: signbit (1);

le dará un 0 como salida (falso)

pero durante el uso de esta función tiene que tener cuidado con cero

std::cout << std::signbit(-0.0); // 512 (true) 
std::cout << std::signbit(+0.0); // 0 (false) 

La salida de estas líneas no son lo mismo.

Para eliminar este problema, puede utilizar:

float x = +0.01; 
std::cout << (x >= 0 ? (x == 0 ? 0 : 1) : -1); 

que dan: [? Guía del principiante absoluto al desplazamiento de bits]

0 for 0 
1 for positive 
-1 for negative 
-1
bool signbit(double x) 
{ 
    return (__int64)x & 0x8000000000000000LL != 0LL; 
} 

bool signbit(float x) 
{ 
    return (__int32)x & 0x80000000 != 0; 
} 
+0

provoca un comportamiento indefinido si 'x' está fuera del rango de' __int64' –

Cuestiones relacionadas