Comment puis-je vérifier si un nombre donné est pair ou impair en C?
Comment puis-je vérifier si un nombre donné est pair ou impair en C?
Réponses:
Utilisez l'opérateur modulo (%) pour vérifier s'il y a un reste lors de la division par 2:
if (x % 2) { /* x is odd */ }
Quelques personnes ont critiqué ma réponse ci-dessus en déclarant que l'utilisation de x & 1 est "plus rapide" ou "plus efficace". Je ne pense pas que ce soit le cas.
Par curiosité, j'ai créé deux programmes de cas de test triviaux:
/* modulo.c */
#include <stdio.h>
int main(void)
{
int x;
for (x = 0; x < 10; x++)
if (x % 2)
printf("%d is odd\n", x);
return 0;
}
/* and.c */
#include <stdio.h>
int main(void)
{
int x;
for (x = 0; x < 10; x++)
if (x & 1)
printf("%d is odd\n", x);
return 0;
}
Je les ai ensuite compilés avec gcc 4.1.3 sur l'une de mes machines 5 fois différentes:
J'ai examiné la sortie d'assemblage de chaque compilation (en utilisant gcc -S) et j'ai constaté que dans chaque cas, la sortie pour and.c et modulo.c étaient identiques (ils utilisaient tous les deux l'instruction andl $ 1,% eax). Je doute que ce soit une "nouvelle" fonctionnalité, et je soupçonne qu'elle remonte à des versions anciennes. Je doute également que tout compilateur moderne (fabriqué au cours des 20 dernières années) non arcane, commercial ou open source, manque d'une telle optimisation. Je testerais sur d'autres compilateurs, mais je n'en ai pas pour le moment.
Si quelqu'un d'autre voulait tester d'autres compilateurs et / ou cibles de plate-forme et obtenir un résultat différent, je serais très intéressé de le savoir.
Enfin, la version modulo est garantie par la norme de fonctionner que l'entier soit positif, négatif ou nul, quelle que soit la représentation de l'implémentation des entiers signés. La version bit à bit et n'est pas. Oui, je me rends compte que le complément à deux est quelque peu omniprésent, donc ce n'est pas vraiment un problème.
Vous êtes waaaaaaaay trop efficaces. Ce que vous voulez vraiment, c'est:
public boolean isOdd(int num) {
int i = 0;
boolean odd = false;
while (i != num) {
odd = !odd;
i = i + 1;
}
return odd;
}
Répétez l'opération pour isEven
.
Bien sûr, cela ne fonctionne pas pour les nombres négatifs. Mais avec éclat vient le sacrifice ...
Utilisez l'arithmétique des bits:
if((x & 1) == 0)
printf("EVEN!\n");
else
printf("ODD!\n");
C'est plus rapide que d'utiliser la division ou le module.
[Mode blague = "on"]
public enum Evenness
{
Unknown = 0,
Even = 1,
Odd = 2
}
public static Evenness AnalyzeEvenness(object o)
{
if (o == null)
return Evenness.Unknown;
string foo = o.ToString();
if (String.IsNullOrEmpty(foo))
return Evenness.Unknown;
char bar = foo[foo.Length - 1];
switch (bar)
{
case '0':
case '2':
case '4':
case '6':
case '8':
return Evenness.Even;
case '1':
case '3':
case '5':
case '7':
case '9':
return Evenness.Odd;
default:
return Evenness.Unknown;
}
}
[Mode blague = "désactivé"]
EDIT: Ajout de valeurs déroutantes à l'énumération.
En réponse à ffpf - j'ai eu exactement le même argument avec un collègue il y a des années, et la réponse est non , cela ne fonctionne pas avec des nombres négatifs.
La norme C stipule que les nombres négatifs peuvent être représentés de 3 manières:
Vérification comme ceci:
isEven = (x & 1);
fonctionnera pour le complément à 2 et le signe et la représentation de l'amplitude, mais pas pour le complément à 1.
Cependant, je pense que ce qui suit fonctionnera dans tous les cas:
isEven = (x & 1) ^ ((-1 & 1) | ((x < 0) ? 0 : 1)));
Merci à ffpf d'avoir souligné que la zone de texte mangeait tout après mon caractère inférieur à!
Un bon est:
/*forward declaration, C compiles in one pass*/
bool isOdd(unsigned int n);
bool isEven(unsigned int n)
{
if (n == 0)
return true ; // I know 0 is even
else
return isOdd(n-1) ; // n is even if n-1 is odd
}
bool isOdd(unsigned int n)
{
if (n == 0)
return false ;
else
return isEven(n-1) ; // n is odd if n-1 is even
}
Notez que cette méthode utilise la récursivité de queue impliquant deux fonctions. Il peut être implémenté efficacement (transformé en une sorte de boucle while / until) si votre compilateur prend en charge la récursivité de queue comme un compilateur Scheme. Dans ce cas, la pile ne doit pas déborder!
Un nombre est pair si, lorsqu'il est divisé par deux, le reste est 0. Un nombre est impair si, lorsqu'il est divisé par 2, le reste est 1.
// Java
public static boolean isOdd(int num){
return num % 2 != 0;
}
/* C */
int isOdd(int num){
return num % 2;
}
Les méthodes sont super!
i % 2 == 0
Je dirais juste le diviser par 2 et s'il y a un reste de 0, c'est pair, sinon c'est impair.
L'utilisation du module (%) facilite cela.
par exemple. 4% 2 = 0 donc 4 est pair 5% 2 = 1 donc 5 est impair
Une solution de plus au problème
(les enfants sont les bienvenus pour voter)
bool isEven(unsigned int x)
{
unsigned int half1 = 0, half2 = 0;
while (x)
{
if (x) { half1++; x--; }
if (x) { half2++; x--; }
}
return half1 == half2;
}
Je construirais un tableau des parités (0 si même 1 si impair) des entiers (donc on pourrait faire une recherche: D), mais gcc ne me laissera pas faire des tableaux de telles tailles:
typedef unsigned int uint;
char parity_uint [UINT_MAX];
char parity_sint_shifted [((uint) INT_MAX) + ((uint) abs (INT_MIN))];
char* parity_sint = parity_sint_shifted - INT_MIN;
void build_parity_tables () {
char parity = 0;
unsigned int ui;
for (ui = 1; ui <= UINT_MAX; ++ui) {
parity_uint [ui - 1] = parity;
parity = !parity;
}
parity = 0;
int si;
for (si = 1; si <= INT_MAX; ++si) {
parity_sint [si - 1] = parity;
parity = !parity;
}
parity = 1;
for (si = -1; si >= INT_MIN; --si) {
parity_sint [si] = parity;
parity = !parity;
}
}
char uparity (unsigned int n) {
if (n == 0) {
return 0;
}
return parity_uint [n - 1];
}
char sparity (int n) {
if (n == 0) {
return 0;
}
if (n < 0) {
++n;
}
return parity_sint [n - 1];
}
Alors, utilisons plutôt la définition mathématique de pair et impair.
Un entier n est même s'il existe un entier k tel que n = 2k.
Un entier n est impair s'il existe un entier k tel que n = 2k + 1.
Voici le code pour cela:
char even (int n) {
int k;
for (k = INT_MIN; k <= INT_MAX; ++k) {
if (n == 2 * k) {
return 1;
}
}
return 0;
}
char odd (int n) {
int k;
for (k = INT_MIN; k <= INT_MAX; ++k) {
if (n == 2 * k + 1) {
return 1;
}
}
return 0;
}
Soit C-entiers les valeurs possibles de int
dans une compilation C donnée. (Notez que les C-entiers sont un sous-ensemble des entiers.)
Maintenant, on pourrait craindre que pour un n donné dans les entiers C, l'entier k correspondant puisse ne pas exister dans les entiers C. Mais avec une petite preuve, on peut montrer que pour tous les entiers n, | n | <= | 2n | (*), où | n | est "n si n est positif et -n sinon". En d'autres termes, pour tous les n en nombres entiers, au moins une des conditions suivantes (exactement soit les cas (1 et 2) soit les cas (3 et 4) en fait, mais je ne le prouverai pas ici):
Cas 1: n <= 2n.
Cas 2: -n <= -2n.
Cas 3: -n <= 2n.
Cas 4: n <= -2n.
Maintenant, prenez 2k = n. (Un tel ak existe si n est pair, mais je ne le prouverai pas ici. Si n n'est pas pair alors la boucle dans even
ne revient pas tôt de toute façon, donc cela n'a pas d'importance.) Mais cela implique k <n si n pas 0 par (*) et le fait (encore une fois non prouvé ici) que pour tout m, z dans les entiers 2m = z implique que z n'est pas égal à m étant donné m n'est pas 0. Dans le cas n est 0, 2 * 0 = 0 donc 0 est pair, nous avons terminé (si n = 0, alors 0 est en C-entiers car n est en C-entier dans la fonction even
, donc k = 0 est en C-entiers). Ainsi, un tel k dans les entiers C existe pour n dans les entiers C si n est pair.
Un argument similaire montre que si n est impair, il existe ak dans les entiers C tels que n = 2k + 1.
Par conséquent , les fonctions even
et odd
présentées ici fonctionnent correctement pour tous les C-entiers.
i % 2
est beaucoup plus petit et probablement plus efficace.
%2
fonctionne pour tous les entiers.
// C#
bool isEven = ((i % 2) == 0);
typedef
ou #define
ou quelque chose.
Voici une réponse en Java:
public static boolean isEven (Integer Number) {
Pattern number = Pattern.compile("^.*?(?:[02]|8|(?:6|4))$");
String num = Number.toString(Number);
Boolean numbr = new Boolean(number.matcher(num).matches());
return numbr.booleanValue();
}
Essaye ça: return (((a>>1)<<1) == a)
Exemple:
a = 10101011
-----------------
a>>1 --> 01010101
a<<1 --> 10101010
b = 10011100
-----------------
b>>1 --> 01001110
b<<1 --> 10011100
En lisant cette discussion plutôt divertissante, je me suis souvenu que j'avais une fonction réelle, sensible au temps, qui testait les nombres pairs et impairs dans la boucle principale. C'est une fonction de puissance entière, publiée ailleurs sur StackOverflow, comme suit. Les repères étaient assez surprenants. Au moins dans cette fonction du monde réel, le modulo est plus lent , et de manière significative. Le gagnant, par une large marge, nécessitant 67% du temps de modulo, est une approche ou (|) , et ne se trouve nulle part ailleurs sur cette page.
static dbl IntPow(dbl st0, int x) {
UINT OrMask = UINT_MAX -1;
dbl st1=1.0;
if(0==x) return (dbl)1.0;
while(1 != x) {
if (UINT_MAX == (x|OrMask)) { // if LSB is 1...
//if(x & 1) {
//if(x % 2) {
st1 *= st0;
}
x = x >> 1; // shift x right 1 bit...
st0 *= st0;
}
return st1 * st0;
}
Pour 300 millions de boucles, les délais de référence sont les suivants.
3.962 le | et approche par masque
4.851 l'approche &
5.850 l'approche%
Pour les personnes qui pensent que la théorie ou une liste de langage d'assemblage règle des arguments comme ceux-ci, cela devrait être un récit édifiant. Il y a plus de choses dans le ciel et la terre, Horatio, que ce dont vous rêvez dans votre philosophie.
unsigned x
tel que le x = x >> 1;
comportement défini par l'implémentation lorsque x < 0
. Pas clair pourquoi x
et OrMask
diffèrent en type. Assez simple pour réécrire à l'aide d'un while(x)
test.
% 2
cas en utilisant le bit &
. Je viens de tester cela et les résultats sont complètement les mêmes (VS2015, versions de version avec toutes les optimisations, x86 et x64). La réponse acceptée l'indique également pour GCC (écrite en 2008).
or
serait plus rapide qu'un an and
est très peu probable, sur n'importe quelle plate-forme / compilateur. Même s'il y avait un combo plateforme / compilateur aussi étrange (et que vous n'avez pas posté ni cela ni le code utilisé pour effectuer le benchmark), dépendre d'autres compilateurs pour se comporter de la même manière serait un mauvais pari d'optimisation. Donc, comme je l'ai écrit, je me demande sur quelle plateforme / compilateur cela a été testé , car je suis presque certain qu'il n'a pas été mesuré correctement.
Il s'agit d'un suivi de la discussion avec @RocketRoy concernant sa réponse , mais il pourrait être utile à quiconque souhaite comparer ces résultats.
tl; dr D'après ce que j'ai vu, l'approche de Roy ( (0xFFFFFFFF == (x | 0xFFFFFFFE)
) n'est pas complètement optimisée pour x & 1
être l' mod
approche, mais dans la pratique, les temps d'exécution devraient se révéler égaux dans tous les cas.
Donc, j'ai d'abord comparé la sortie compilée à l'aide de l' explorateur de compilateur :
Fonctions testées:
int isOdd_mod(unsigned x) {
return (x % 2);
}
int isOdd_and(unsigned x) {
return (x & 1);
}
int isOdd_or(unsigned x) {
return (0xFFFFFFFF == (x | 0xFFFFFFFE));
}
CLang 3.9.0 avec -O3:
isOdd_mod(unsigned int): # @isOdd_mod(unsigned int)
and edi, 1
mov eax, edi
ret
isOdd_and(unsigned int): # @isOdd_and(unsigned int)
and edi, 1
mov eax, edi
ret
isOdd_or(unsigned int): # @isOdd_or(unsigned int)
and edi, 1
mov eax, edi
ret
GCC 6.2 avec -O3:
isOdd_mod(unsigned int):
mov eax, edi
and eax, 1
ret
isOdd_and(unsigned int):
mov eax, edi
and eax, 1
ret
isOdd_or(unsigned int):
or edi, -2
xor eax, eax
cmp edi, -1
sete al
ret
Chapeau à CLang, il s'est rendu compte que les trois cas sont fonctionnellement égaux. Cependant, l'approche de Roy n'est pas optimisée dans GCC, donc YMMV.
C'est similaire avec Visual Studio; en inspectant le démontage Release x64 (VS2015) pour ces trois fonctions, j'ai pu voir que la partie de comparaison est égale pour les cas "mod" et "et", et légèrement plus grande pour le cas Roy ou ":
// x % 2
test bl,1
je (some address)
// x & 1
test bl,1
je (some address)
// Roy's bitwise or
mov eax,ebx
or eax,0FFFFFFFEh
cmp eax,0FFFFFFFFh
jne (some address)
Cependant, après avoir exécuté un benchmark réel pour comparer ces trois options (mod simple, bit à bit ou, bit à bit et), les résultats étaient complètement égaux (encore une fois, Visual Studio 2005 x86 / x64, version Release, aucun débogueur attaché).
L'assemblage de version utilise l' test
instruction pour and
et les mod
cas, tandis que le cas de Roy utilise l' cmp eax,0FFFFFFFFh
approche, mais il est fortement déroulé et optimisé, donc il n'y a pas de différence dans la pratique.
Mes résultats après 20 exécutions (i7 3610QM, plan d'alimentation Windows 10 défini sur Haute performance):
[Test: Plain mod 2] TEMPS MOYEN: 689,29 ms (Diff relative: + 0,000%) [Test: au niveau du bit ou] TEMPS MOYEN: 689,63 ms (diff. Relative: + 0,048%) [Test: au niveau du bit et] TEMPS MOYEN: 687,80 ms (diff. Relative: -0,217%)
La différence entre ces options est inférieure à 0,3%, il est donc assez évident que l'assemblage est égal dans tous les cas.
Voici le code si quelqu'un veut essayer, avec une mise en garde que je ne l'ai testé que sur Windows (vérifiez le #if LINUX
conditionnel pour la get_time
définition et implémentez-le si nécessaire, tiré de cette réponse ).
#include <stdio.h>
#if LINUX
#include <sys/time.h>
#include <sys/resource.h>
double get_time()
{
struct timeval t;
struct timezone tzp;
gettimeofday(&t, &tzp);
return t.tv_sec + t.tv_usec*1e-6;
}
#else
#include <windows.h>
double get_time()
{
LARGE_INTEGER t, f;
QueryPerformanceCounter(&t);
QueryPerformanceFrequency(&f);
return (double)t.QuadPart / (double)f.QuadPart * 1000.0;
}
#endif
#define NUM_ITERATIONS (1000 * 1000 * 1000)
// using a macro to avoid function call overhead
#define Benchmark(accumulator, name, operation) { \
double startTime = get_time(); \
double dummySum = 0.0, elapsed; \
int x; \
for (x = 0; x < NUM_ITERATIONS; x++) { \
if (operation) dummySum += x; \
} \
elapsed = get_time() - startTime; \
accumulator += elapsed; \
if (dummySum > 2000) \
printf("[Test: %-12s] %0.2f ms\r\n", name, elapsed); \
}
void DumpAverage(char *test, double totalTime, double reference)
{
printf("[Test: %-12s] AVERAGE TIME: %0.2f ms (Relative diff.: %+6.3f%%)\r\n",
test, totalTime, (totalTime - reference) / reference * 100.0);
}
int main(void)
{
int repeats = 20;
double runningTimes[3] = { 0 };
int k;
for (k = 0; k < repeats; k++) {
printf("Run %d of %d...\r\n", k + 1, repeats);
Benchmark(runningTimes[0], "Plain mod 2", (x % 2));
Benchmark(runningTimes[1], "Bitwise or", (0xFFFFFFFF == (x | 0xFFFFFFFE)));
Benchmark(runningTimes[2], "Bitwise and", (x & 1));
}
{
double reference = runningTimes[0] / repeats;
printf("\r\n");
DumpAverage("Plain mod 2", runningTimes[0] / repeats, reference);
DumpAverage("Bitwise or", runningTimes[1] / repeats, reference);
DumpAverage("Bitwise and", runningTimes[2] / repeats, reference);
}
getchar();
return 0;
}
Je sais que c'est juste du sucre syntaxique et uniquement applicable en .net mais qu'en est-il de la méthode d'extension ...
public static class RudiGroblerExtensions
{
public static bool IsOdd(this int i)
{
return ((i % 2) != 0);
}
}
Vous pouvez maintenant effectuer les opérations suivantes
int i = 5;
if (i.IsOdd())
{
// Do something...
}
Dans la "catégorie créative mais déroutante" je vous propose:
int isOdd(int n) { return n ^ n * n ? isOdd(n * n) : n; }
Une variante de ce thème spécifique à Microsoft C ++:
__declspec(naked) bool __fastcall isOdd(const int x)
{
__asm
{
mov eax,ecx
mul eax
mul eax
mul eax
mul eax
mul eax
mul eax
ret
}
}
La méthode au niveau du bit dépend de la représentation interne de l'entier. Modulo fonctionnera partout où il y a un opérateur modulo. Par exemple, certains systèmes utilisent en fait les bits de bas niveau pour le balisage (comme les langages dynamiques), donc le x & 1 brut ne fonctionnera pas réellement dans ce cas.
IsOdd (int x) {return true; }
Preuve d'exactitude - considérez l'ensemble de tous les entiers positifs et supposez qu'il existe un ensemble non vide d'entiers qui ne sont pas impairs. Parce que les entiers positifs sont bien ordonnés, il y aura un plus petit nombre non impair, qui en soi est assez impair, si clairement que ce nombre ne peut pas être dans l'ensemble. Par conséquent, cet ensemble ne peut pas être non vide. Répétez l'opération pour les nombres entiers négatifs, sauf recherchez le plus grand nombre non impair.
Comme certaines personnes l'ont signalé, il existe de nombreuses façons de procéder. Selon ce site , le moyen le plus rapide est l'opérateur de module:
if (x % 2 == 0)
total += 1; //even number
else
total -= 1; //odd number
Cependant, voici un autre code qui a été marqué par l'auteur et qui a fonctionné plus lentement que l'opération de module commune ci-dessus:
if ((x & 1) == 0)
total += 1; //even number
else
total -= 1; //odd number
System.Math.DivRem((long)x, (long)2, out outvalue);
if ( outvalue == 0)
total += 1; //even number
else
total -= 1; //odd number
if (((x / 2) * 2) == x)
total += 1; //even number
else
total -= 1; //odd number
if (((x >> 1) << 1) == x)
total += 1; //even number
else
total -= 1; //odd number
while (index > 1)
index -= 2;
if (index == 0)
total += 1; //even number
else
total -= 1; //odd number
tempstr = x.ToString();
index = tempstr.Length - 1;
//this assumes base 10
if (tempstr[index] == '0' || tempstr[index] == '2' || tempstr[index] == '4' || tempstr[index] == '6' || tempstr[index] == '8')
total += 1; //even number
else
total -= 1; //odd number
Combien de personnes connaissaient même la méthode Math.System.DivRem ou pourquoi l'utilisaient-elles ??
Pour donner plus de détails sur la méthode de l'opérateur au niveau du bit pour ceux d'entre nous qui n'ont pas fait beaucoup d'algèbre booléenne pendant nos études, voici une explication. Probablement pas d'une grande utilité pour l'OP, mais j'avais envie de préciser pourquoi NUMBER & 1 fonctionne.
Veuillez noter que, comme quelqu'un a répondu ci-dessus, la façon dont les nombres négatifs sont représentés peut empêcher cette méthode de fonctionner. En fait, il peut même casser la méthode de l'opérateur modulo, car chaque langue peut différer dans la façon dont elle traite les opérandes négatifs.
Cependant, si vous savez que NUMBER sera toujours positif, cela fonctionne bien.
Comme Tooony ci-dessus a fait remarquer que seul le dernier chiffre en binaire (et déni) est important.
Une logique booléenne ET porte que les deux entrées doivent être un 1 (ou haute tension) pour que 1 soit renvoyé.
1 & 0 = 0.
0 & 1 = 0.
0 et 0 = 0.
1 & 1 = 1.
Si vous représentez n'importe quel nombre comme binaire (j'ai utilisé une représentation sur 8 bits ici), les nombres impairs ont 1 à la fin, les nombres pairs ont 0.
Par exemple:
1 = 00000001
2 = 00000010
3 = 00000011
4 = 00000100
Si vous prenez un nombre et utilisez ET au niveau du bit (& en java) par 1, il retournera soit 00000001, = 1, ce qui signifie que le nombre est impair. Ou 00000000 = 0, ce qui signifie que le nombre est pair.
Par exemple
Est impair?
1 & 1 =
00000001 &
00000001 =
00000001 <- Impair
2 & 1 =
00000010 &
00000001 =
00000000 <- Pair
54 & 1 =
00000001 &
00110110 =
00000000 <- Pair
C'est pourquoi cela fonctionne:
if(number & 1){
//Number is odd
} else {
//Number is even
}
Désolé si c'est redondant.
Parité zéro | zéro http://tinyurl.com/oexhr3k
Séquence de code Python.
# defining function for number parity check
def parity(number):
"""Parity check function"""
# if number is 0 (zero) return 'Zero neither ODD nor EVEN',
# otherwise number&1, checking last bit, if 0, then EVEN,
# if 1, then ODD.
return (number == 0 and 'Zero neither ODD nor EVEN') \
or (number&1 and 'ODD' or 'EVEN')
# cycle trough numbers from 0 to 13
for number in range(0, 14):
print "{0:>4} : {0:08b} : {1:}".format(number, parity(number))
Production:
0 : 00000000 : Zero neither ODD nor EVEN
1 : 00000001 : ODD
2 : 00000010 : EVEN
3 : 00000011 : ODD
4 : 00000100 : EVEN
5 : 00000101 : ODD
6 : 00000110 : EVEN
7 : 00000111 : ODD
8 : 00001000 : EVEN
9 : 00001001 : ODD
10 : 00001010 : EVEN
11 : 00001011 : ODD
12 : 00001100 : EVEN
13 : 00001101 : ODD
I execute this code for ODD & EVEN:
#include <stdio.h>
int main()
{
int number;
printf("Enter an integer: ");
scanf("%d", &number);
if(number % 2 == 0)
printf("%d is even.", number);
else
printf("%d is odd.", number);
}
Par souci de discussion ...
Il vous suffit de regarder le dernier chiffre d'un nombre donné pour voir s'il est pair ou impair. Signé, non signé, positif, négatif - ils sont tous les mêmes à ce sujet. Donc, cela devrait fonctionner tout autour: -
void tellMeIfItIsAnOddNumberPlease(int iToTest){
int iLastDigit;
iLastDigit = iToTest - (iToTest / 10 * 10);
if (iLastDigit % 2 == 0){
printf("The number %d is even!\n", iToTest);
} else {
printf("The number %d is odd!\n", iToTest);
}
}
La clé ici est dans la troisième ligne de code, l'opérateur de division effectue une division entière, de sorte que le résultat manque la partie fraction du résultat. Ainsi, par exemple, 222/10 donnera 22 comme résultat. Ensuite, multipliez-le à nouveau avec 10 et vous avez 220. Soustrayez cela de l'original 222 et vous vous retrouvez avec 2, qui par magie est le même nombre que le dernier chiffre du nombre d'origine. ;-) Les parenthèses sont là pour nous rappeler l'ordre dans lequel le calcul est effectué. Effectuez d'abord la division et la multiplication, puis soustrayez le résultat du nombre d'origine. Nous pourrions les laisser de côté, car la priorité est plus élevée pour la division et la multiplication que pour la soustraction, mais cela nous donne un code "plus lisible".
Nous pourrions tout rendre complètement illisible si nous le voulions. Cela ne ferait aucune différence pour un compilateur moderne: -
printf("%d%s\n",iToTest,0==(iToTest-iToTest/10*10)%2?" is even":" is odd");
Mais cela rendrait le code plus difficile à maintenir à l'avenir. Imaginez simplement que vous souhaitez changer le texte des nombres impairs en "n'est pas pair". Plus tard, quelqu'un d'autre voudra savoir quelles modifications vous avez apportées et effectuer un diff svn ou similaire ...
Si vous n'êtes pas préoccupé par la portabilité mais plutôt par la vitesse, vous pouvez jeter un œil au bit le moins significatif. Si ce bit est mis à 1 c'est un nombre impair, s'il est 0 c'est un nombre pair. Sur un petit système endian, comme l'architecture x86 d'Intel, ce serait quelque chose comme ceci: -
if (iToTest & 1) {
// Even
} else {
// Odd
}
Si vous voulez être efficace, utilisez des opérateurs au niveau du bit ( x & 1
), mais si vous voulez être lisible, utilisez modulo 2 ( x % 2
)
%
. Si vous voulez qu'il soit lisible, utilisez %
. Hmmm, je vois un motif ici.
Vérifier pair ou impair est une tâche simple.
Nous savons que tout nombre exactement divisible par 2 est un nombre pair impair.
Nous avons juste besoin de vérifier la divisibilité de n'importe quel nombre et pour vérifier la divisibilité, nous utilisons l' %
opérateur
Vérifier même impair en utilisant sinon
if(num%2 ==0)
{
printf("Even");
}
else
{
printf("Odd");
}
Programme C pour vérifier pair ou impair en utilisant sinon
Utilisation de l'opérateur conditionnel / ternaire
(num%2 ==0) printf("Even") : printf("Odd");
Programme C pour vérifier pair ou impair en utilisant l'opérateur conditionnel .
Utilisation de l'opérateur Bitwise
if(num & 1)
{
printf("Odd");
}
else
{
printf("Even");
}
!(i%2) / i%2 == 0
int isOdd(int n)
{
return n & 1;
}
Le code vérifie le dernier bit de l'entier s'il est 1 en binaire
Binary : Decimal
-------------------
0000 = 0
0001 = 1
0010 = 2
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = 8
1001 = 9
and so on...
Notez que le bit le plus à droite est toujours 1 pour les nombres impairs .
les & contrôles de niveau du bit et le bit opérateur dans notre extrême droite retour ligne si c'est 1
Lorsque nous comparons n avec 1, ce qui signifie 0001
en binaire (le nombre de zéros n'a pas d'importance).
Imaginons alors que nous avons l'entier n avec une taille de 1 octet.
Il serait représenté par des chiffres 8 bits / 8 bits.
Si l'int n était 7 et que nous le comparons à 1 , c'est comme
7 (1-byte int)| 0 0 0 0 0 1 1 1
&
1 (1-byte int)| 0 0 0 0 0 0 0 1
********************************************
Result | F F F F F F F T
Quel F signifie faux et T pour vrai.
Il ne compare que le bit le plus à droite s'ils sont tous les deux vrais. Donc, automagiquement,
7 & 1
c'est T rue.
Changez simplement n & 1
à n & 2
quel 2 représente 0010
en binaire et ainsi de suite.
Je suggère d'utiliser la notation hexadécimale si vous débutez dans les opérations au niveau du bit
return n & 1;
>> return n & 0x01;
.