2010-06-08 8 views
7

Voglio poter accedere al bit di segno di un numero in C++. Il mio codice corrente simile a questa:Come posso accedere al bit di segno di un numero in C++?

int sign bit = number >> 31; 

Questo sembra funzionare, dandomi 0 per i numeri positivi e -1 per i numeri negativi. Tuttavia, non vedo come ottenere -1 per i numeri negativi: se 12 è

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

poi -12 è

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

e spostandolo 31 bit renderebbe

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

che è 1, non -1, quindi perché ottengo -1 quando lo sposto?

+0

possibile duplicato (http: // StackOverflow. it/questions/141525/absolute-beginners-guide-to-bit-shifting) – msw

+0

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

+5

Per [complemento a due] (http://en.wikipedia.org/wiki/Two%27s_complement#Complement_of_a_positive_number) (che utilizzano i sistemi più moderni), il tuo -12 è sbagliato. Dovrebbe terminare 0100. –

risposta

11

Il risultato del corretto spostamento di un numero negativo in C++ è definito dall'implementazione. Quindi, nessuno sa cosa sia giusto spostare il tuo -12 sulla tua piattaforma specifica. Pensi che dovrebbe fare quanto sopra (1), mentre io dico che può facilmente produrre un modello tutto-uno, che è -1. Quest'ultimo è chiamato spostamento esteso al segno. Nello slittamento esteso al segno, il bit del segno viene copiato a destra, ma non viene mai spostato fuori dalla sua posizione.

Se tutto ciò che ti interessa è il valore del bit di segno, quindi smettere di sprecare tempo cercando di utilizzare operazioni bit a bit, come turni ecc. Basta confrontare il tuo numero su 0 e vedere se è negativo o meno.

+1

Questo è un post davvero vecchio ma ho appena visto questo mentre cercavo qualcos'altro. Sono generalmente d'accordo con quello che stai dicendo qui. Ma ci sono alcune supposizioni fatte nella sua domanda che potrebbero aver contribuito all'esito del suo codice. Questo può essere fatto in modo indipendente usando lo spostamento dei bit o semplicemente usando una maschera bit per controllare il bit del segno. –

+0

Ciò non distingue -0.0 da +0.0. È necessario accedere al bit di segno per quello. Vedi la risposta di Giovanni. –

+0

@NeilG In base al testo nella domanda, mi sembra che mi chieda di numeri interi. –

24

Che dire di questo?

int sign = number < 0;

2

L'operatore >> sta eseguendo un arithmetic shift, che conserva il segno del numero.

+4

No. Quale tipo di spostamento viene eseguito dall'operatore '>>' è definito dall'implementazione. Potrebbe essere un qualsiasi tipo di cambiamento. – AnT

+0

@AndreyT: Ho detto "l'operatore' >> 'sta eseguendo uno spostamento aritmetico", e questo è esattamente ciò che sta facendo in questo caso, a giudicare dalla descrizione dell'OP. Si noti che I * non ha * detto "l'operatore' >> 'esegue sempre uno spostamento aritmetico" o qualcosa del genere. Forse avrei dovuto essere più esplicito, ma in entrambi i casi, non credo che la mia risposta meriti un downvote. – LukeH

+2

@Downvoters: si prega di giustificare voi stessi. Ho spiegato * esattamente * qual è il problema dell'OP. Non ho avanzato affermazioni come "l'operatore' >> "esegue sempre uno spostamento aritmetico"; Ho spiegato * esattamente * ciò che l'operatore '>>' sta facendo * in questo caso particolare *. – LukeH

7

Poiché si sta spostando il numero intero con segno. Gettate l'intero a non firmato:

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

Per gli interi, prova number < 0.

Per i numeri in virgola mobile, è anche possibile prendere in considerazione il fatto che lo zero ha un segno. Cioè esiste un -0.0 che è distinto da +0.0. Per distinguere i due, si desidera utilizzare std::signbit.

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

La mia soluzione che supporta +/- 0.

2

È possibile utilizzare libreria cmath

#include <cmath> 

e utilizzarlo come

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

Questa funzione ottenere un valore float come input e un valore bool come output.

true for negative 
false for positive 

per esempio

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

vi darà uno 0 come uscita (false)

ma durante l'utilizzo di questa funzione bisogna stare attenti circa zero

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

L'uscita di questo linee non sono gli stessi.

Per rimuovere questo problema è possibile utilizzare:

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

che danno: [? Guida di Absolute Beginner a Bit Shifting]

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

causa un comportamento indefinito se 'x' non rientra nell'intervallo di' __int64' –

Problemi correlati