31 votes

Trouver si un entier signé et un entier non signé sont tous les deux pairs ou les deux impairs

J'ai un int m et unsigned int j et souhaitez afin de déterminer si elles sont à la fois même ou les deux impairs.

Dans le passé, j'ai été en utilisant

if((int(j)+m)%2)

pour attraper les cas que un seul est impair. Mais je m'inquiète de la conversion en int une modification incorrecte de la paire-impaire-ness de j.

Effectuez l'une de ces problèmes?

if(!(j%2)!=!(m%2))
if(bool(j%2)!=bool(j%2))

Je sais que

if(j%2!=m%2)

ne fonctionne pas parce que 'm%2' produira -1 lorsque m est négative, ce qui vous permettra de toujours évaluer à l' true quelle que soit la valeur de j%2 est.

63voto

Barry Points 45207

N'utilisez pas % . C'est un problème qui appelle des masques de bits:

 bool same_parity = (i & 0x1) == (j & 0x1);
 

Cela fonctionne quel que soit le signe i , car le résultat de cette expression sera toujours 0 ou 1 .

56voto

SolutionMill Points 645
if (1 & (i ^ j))
{
// Getting here if i is even and j is odd
// or if i is odd and j is even
}

^ est le exclusive-or opérateur au niveau du bit, qui vérifie chaque bit à la fois en nombre si elles ont la même valeur. Par exemple, si la représentation binaire de l' i est 0101 et j est 1100, alors i ^ j donnera 1001, depuis leurs premiers et derniers bits sont différents, alors que le milieu de bits sont les mêmes.

& est le and opérateur au niveau du bit, qui vérifie chaque bit à la fois en nombre si ils sont à la fois 1.

Depuis le dernier bit de chaque nombre détermine s'il est pair ou impair, i ^ j donnera ...xxx0 si ils sont tous les deux pairs ou impairs, et ...xxx1 sinon (l' xs n'a pas d'importance, nous ne regardons pas à eux de toute façon). Depuis 1 est en fait ...0001, 1 & (i ^ j) évalue 0 si i et j sont tous les deux pairs ou impairs, et 1 sinon.

Cela fonctionne sur n'importe quelle combinaison de nombres non signés, 2s-compléter et signer-et-ampleur, mais pas les rares 1s-complément si exactement l'un est négatif.

19voto

Matt McNabb Points 14273

L'ajout de deux entiers ajoute leur parité, donc la solution est simple:

if ( (j + m) % 2 )

Unsigned wraparound ne pas déranger cette propriété, car il est fait modulo UINT_MAX+1 ce qui est un nombre pair.

Cette solution ne dépend pas d'une implementatation des détails spécifiques tels que le nombre négatif de la représentation.


Note de bas de page: j'ai du mal à voir pourquoi tant de nombreuses autres réponses sont déterminés à compliquer le problème avec bit-quarts, bit-complète, XORs, etc. etc. Malheureusement, l'OMI, il est parfois glorifié dans le C ou C++ communautés à l'écriture délicate de code au lieu de code simple.

16voto

Yakk Points 31636

Le coulage d'un unsigned int qui est plus grand que INT_MAX de int n'est pas garantie pour renvoyer un bon de valeur. Le résultat est indéfini.

Le coulage d'un int d'un unsigned int toujours des résultats définis dans le comportement, car il n'en mathématiques mod 2^k pour certains k assez grande pour que chaque positifs int est inférieure à 2^k.

if((int(j)+m)%2)

devrait être

if((j+unsigned(m))%2)

au lieu de cela.

if((j%2)==(unsigned(m)%2))

est la meilleure façon de voir si les deux ont la même parité. Le déplacement vers unsigned aka mod 2^k va maintenir la parité, et en unsigned %2 renvoie la parité correctement (et pas négatif de la parité).

6voto

plats1 Points 530

Ne pas être trop intelligent

Effectuez l'une de ces problèmes?

if(!(j%2)!=!(m%2))
if(bool(j%2)!=bool(j%2))

Un problème que je vois est la lisibilité. Il pourrait ne pas être évident pour quelqu'un d'autre (ou de votre soi futur) ce qu'il est censé faire ou ce qu'il fait réellement.

Vous pourriez être plus expressif de passer quelques lignes supplémentaires:

#include <cmath>

const bool fooIsEven = foo % 2 == 0;
const bool barIsEven = std::abs(bar) % 2 == 0;
if (fooIsEven == barIsEven)
{
  // ...
}

Également envisager de mettre en œuvre un bien nommé la fonction qui fournit une comparaison de la parité de deux types intégraux. Ce n'est pas seulement nettoie votre code, mais aussi vous empêche de vous répéter vous-même.

Edit: Remplacé exprimés par appel à std::abs

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X