Vérifier si un nombre est positif ou négatif en utilisant des opérateurs bitwise
je peux vérifier si un nombre est impair/même en utilisant des opérateurs bitwise. Puis-je vérifier si un nombre est positif/zéro/négatif sans utiliser de déclarations conditionnelles/opérateurs comme if/ternary etc.
peut-on faire la même chose en utilisant des opérateurs bitwise et un truc en c/" class="blnk">C ou en C++?
15 réponses
puis-je vérifier si un nombre est positif/zéro/négatif sans utiliser de déclarations conditionnelles/opérateurs comme if/ternary etc.
bien sûr:
bool is_positive = number > 0;
bool is_negative = number < 0;
bool is_zero = number == 0;
si le high bit est défini sur un entier signé (byte, long, etc., mais pas un nombre flottant), ce nombre est négatif.
int x = -2300; // assuming a 32-bit int
if ((x & 0x80000000) != 0)
{
// number is negative
}
ajouté:
vous avez dit que Vous ne voulez pas utiliser le conditionnel. Je suppose que tu peux faire ceci:
int isNegative = (x & 0x80000000);
Et au bout d'un certain temps, vous pouvez tester avec if (isNegative)
.
Il y a une discussion détaillée sur le Bit se Tourner les Hacks page.
int v; // we want to find the sign of v
int sign; // the result goes here
// CHAR_BIT is the number of bits per byte (normally 8).
sign = -(v < 0); // if v < 0 then -1, else 0.
// or, to avoid branching on CPUs with flag registers (IA32):
sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
// or, for one less instruction (but not portable):
sign = v >> (sizeof(int) * CHAR_BIT - 1);
// The last expression above evaluates to sign = v >> 31 for 32-bit integers.
// This is one operation faster than the obvious way, sign = -(v < 0). This
// trick works because when signed integers are shifted right, the value of the
// far left bit is copied to the other bits. The far left bit is 1 when the value
// is negative and 0 otherwise; all 1 bits gives -1. Unfortunately, this behavior
// is architecture-specific.
// Alternatively, if you prefer the result be either -1 or +1, then use:
sign = +1 | (v >> (sizeof(int) * CHAR_BIT - 1)); // if v < 0 then -1, else +1
// On the other hand, if you prefer the result be either -1, 0, or +1, then use:
sign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
// Or, for more speed but less portability:
sign = (v != 0) | (v >> (sizeof(int) * CHAR_BIT - 1)); // -1, 0, or +1
// Or, for portability, brevity, and (perhaps) speed:
sign = (v > 0) - (v < 0); // -1, 0, or +1
// If instead you want to know if something is non-negative, resulting in +1
// or else 0, then use:
sign = 1 ^ ((unsigned int)v >> (sizeof(int) * CHAR_BIT - 1)); // if v < 0 then 0, else 1
// Caveat: On March 7, 2003, Angus Duggan pointed out that the 1989 ANSI C
// specification leaves the result of signed right-shift implementation-defined,
// so on some systems this hack might not work. For greater portability, Toby
// Speight suggested on September 28, 2005 that CHAR_BIT be used here and
// throughout rather than assuming bytes were 8 bits long. Angus recommended
// the more portable versions above, involving casting on March 4, 2006.
// Rohit Garg suggested the version for non-negative integers on September 12, 2009.
Ou, vous pouvez utiliser signbit()
et le travail est fait pour vous.
je suppose que sous le capot, le math.h
la mise en œuvre est une vérification bitwise efficace (peut-être la résolution de votre objectif original).
Référence: http://en.cppreference.com/w/cpp/numeric/math/signbit
#include<stdio.h>
void main()
{
int n; // assuming int to be 32 bit long
//shift it right 31 times so that MSB comes to LSB's position
//and then and it with 0x1
if ((n>>31) & 0x1 == 1) {
printf("negative number\n");
} else {
printf("positive number\n");
}
getch();
}
les entiers signés et les points flottants utilisent normalement le bit le plus significatif pour stocker le signe donc si vous connaissez la taille, vous pouvez extraire l'information du bit le plus significatif.
il y a généralement peu d'avantages à faire cela car une sorte de comparaison devra être faite pour utiliser cette information et il est tout aussi facile pour un processeur de tester si quelque chose est négatif que de tester si ce n'est pas zéro. Si fait sur les processeurs de bras, vérifier le plus un bit significatif sera normalement plus coûteux que de vérifier s'il est négatif au départ.
C'est assez simple
Il peut être fait facilement par
return ((!!x) | (x >> 31));
retourne
- 1 pour un nombre positif,
- -1 pour un négatif, et
- 0 pour zéro
// if (x < 0) return -1
// else if (x == 0) return 0
// else return 1
int sign(int x) {
// x_is_not_zero = 0 if x is 0 else x_is_not_zero = 1
int x_is_not_zero = (( x | (~x + 1)) >> 31) & 0x1;
return (x & 0x01 << 31) >> 31 | x_is_not_zero; // for minux x, don't care the last operand
}
Voici exactement ce que vous quel!
cela ne peut pas être fait d'une manière portable avec des opérations de bits dans C. Les représentations pour les types entiers signés que la norme autorise peuvent être beaucoup plus bizarres que vous pourriez le soupçonner. En particulier, la valeur avec signe bit on et autrement zéro ne doit pas nécessairement être une valeur admissible pour le type signé ni pour le type non signé, mais une représentation dite piège pour les deux types.
tous les calculs avec des opérateurs de bits que vous pouvez donc faire pourraient avoir un résultat qui conduit à des comportement.
dans tous les cas comme le suggèrent certaines autres réponses, ce n'est pas vraiment nécessaire et la comparaison avec <
ou >
devrait suffire dans tout contexte pratique, plus efficace, plus facile à lire... si juste de le faire de cette façon.
if( (num>>sizeof(int)*8 - 1) == 0 )
// number is positive
else
// number is negative
si la valeur est 0 alors le nombre est positif sinon négatif
Un moyen simple de savoir si un nombre est positif ou négatif: Que le nombre soit x vérifier si [x * (-1)] > X. si le vrai x est négatif, il est positif.
Vous pouvez différencier les négatifs/non négatif en regardant le bit le plus significatif. Dans toutes les représentations pour les entiers signés, ce bit sera fixé à 1 si le nombre est négatif.
il n'y a pas de test pour distinguer le zéro du positif, sauf pour un test direct contre 0.
À tester pour le négatif, vous pouvez utiliser
#define IS_NEGATIVE(x) ((x) & (1U << ((sizeof(x)*CHAR_BIT)-1)))
supposons que votre numéro soit a=10
(positif). Si vous maj a
a
fois, il donnera à zéro.
j'.e:
10>>10 == 0
ainsi vous pouvez vérifier si le nombre est positif, mais dans le cas a=-10
(négatif):
-10>>-10 == -1
vous pouvez donc les combiner dans un if
:
if(!(a>>a))
print number is positive
else
print no. is negative
quand vous êtes sûr de la taille d'un entier (en supposant que 16 bits int):
bool is_negative = (unsigned) signed_int_value >> 15;
Lorsque vous n'êtes pas sûr de la taille des entiers:
bool is_negative = (unsigned) signed_int_value >> (sizeof(int)*8)-1; //where 8 is bits
unsigned
mot clé est facultatif.
Voici une mise à jour relative à C++11 pour cette ancienne question. Il vaut également la peine d'envisager std:: signbit.
sur L'Explorateur de compilateur utilisant gcc 7.3 64bit avec l'optimisation-O3, ce code
bool s1(double d)
{
return d < 0.0;
}
produit
s1(double):
pxor xmm1, xmm1
ucomisd xmm1, xmm0
seta al
ret
et ce code
bool s2(double d)
{
return std::signbit(d);
}
produit
s2(double):
movmskpd eax, xmm0
and eax, 1
ret
vous auriez besoin de profiler pour vous assurer qu'il y a une différence de vitesse, mais la version signbit utilise 1 opcode de moins.