2010-06-08 9 views
7

Je veux être en mesure d'accéder au bit de signe d'un nombre en C++. Mon code actuel ressemble à ceci:Comment puis-je accéder au bit de signe d'un nombre en C++?

int sign bit = number >> 31; 

Cela semble fonctionner, me donner 0 pour les nombres positifs et -1 pour les nombres négatifs. Cependant, je ne vois pas comment je me -1 pour les nombres négatifs: si 12 est

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

puis -12 est

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

et décalant 31 bits feraient

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

ce qui est 1, pas -1, alors pourquoi ai-je -1 quand je le change?

+0

double possible (http: // stackoverflow. com/questions/141525/absolute-beginners-guide-to-bit-shifting) – msw

+0

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

+5

Pour [complément à deux] (http://en.wikipedia.org/wiki/Two%27s_complement#Complement_of_a_positive_number) (que les systèmes les plus modernes utilisent), votre -12 est faux. Il devrait se terminer à 0100. –

Répondre

11

Le résultat du décalage vers la droite d'un nombre négatif en C++ est défini par l'implémentation. Donc, personne ne sait ce que votre -12 devrait faire sur votre plate-forme spécifique. Vous pensez qu'il devrait faire ce qui précède (1), alors que je dis qu'il peut facilement produire un motif all-ones, qui est -1. Ce dernier est appelé changement de signe étendu. Dans le changement de signe prolongé, le bit de signe est copié vers la droite, mais jamais déplacé hors de sa place. Si tout ce qui vous intéresse est la valeur du bit de signe, alors arrêtez de perdre du temps en essayant d'utiliser des opérations au niveau du bit, comme les décalages etc. Comparez simplement votre nombre à 0 et voyez s'il est négatif ou non. Parce que vous déplacez l'entier signé.

+1

Ceci est un très vieux post mais je viens de le voir en cherchant autre chose. Je suis généralement d'accord avec ce que vous dites ici. Mais il a fait certaines hypothèses dans sa question qui auraient pu contribuer à l'aboutissement de son code. Cela peut être fait en archi indépendamment en utilisant le décalage de bits ou simplement en utilisant un bit-mask pour vérifier le bit de signe. –

+0

Cela ne distingue pas -0,0 de +0,0. Vous devez accéder au signe pour cela. Voir la réponse de John. –

+0

@NeilG Basé sur le texte de la question, il me semble poser des questions sur les entiers. –

24

Que pensez-vous de cela?

int sign = number < 0;

2

L'opérateur >> effectue une arithmetic shift, qui conserve le signe du nombre.

+4

Non. Quel type de décalage est effectué par l'opérateur '>>' est défini par l'implémentation. Pourrait être n'importe quel type de changement. – AnT

+0

@AndreyT: J'ai dit "l'opérateur >>' 'effectue un changement arithmétique", et c'est exactement ce qu'il fait dans ce cas, à en juger par la description de l'OP. Remarquez que je n'ai pas dit que l'opérateur '>>' 'effectue toujours un changement arithmétique" ou quelque chose comme ça. Peut-être aurais-je dû être plus explicite, mais de toute façon, je ne pense pas que ma réponse mérite un downvote. – LukeH

+2

@Downvoters: Veuillez vous justifier. J'ai expliqué * exactement * quel est le problème du PO. Je n'ai pas fait de revendications générales comme "l'opérateur' '' 'effectue toujours un changement arithmétique"; J'ai expliqué * exactement * ce que fait l'opérateur '>>' dans ce cas particulier *. – LukeH

7

Couler le nombre entier non signé à:

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

Pour les entiers, le test number < 0.

Pour les nombres à virgule flottante, vous pouvez également prendre en compte le fait que zéro a un signe. Autrement dit, il existe un -0,0 qui est distinct de +0,0. Pour distinguer les deux, vous souhaitez utiliser std::signbit.

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

Ma solution qui prend en charge +/- 0.

2

Vous pouvez utiliser la bibliothèque cmath

#include <cmath> 

et de l'utiliser comme

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

Cette fonction obtenir une valeur flottante en entrée et une valeur bool en sortie.

true for negative 
false for positive 

par exemple

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

vous donnera un 0 en sortie (false)

mais en utilisant cette fonction, vous devez faire attention à zéro

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

La sortie de ces lignes ne sont pas les mêmes.

Pour supprimer ce problème, vous pouvez utiliser:

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

qui donnent: [? Guide de débutant absolu à décalage 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

provoque un comportement indéfini si 'x' est hors de portée de' __int64' –