Come posso verificare se un dato numero è pari o dispari in C?
Come posso verificare se un dato numero è pari o dispari in C?
Risposte:
Usa l'operatore modulo (%) per verificare se c'è un resto quando dividi per 2:
if (x % 2) { /* x is odd */ }
Alcune persone hanno criticato la mia risposta sopra affermando che l'uso di x & 1 è "più veloce" o "più efficiente". Non credo che sia così.
Per curiosità, ho creato due banali programmi per test case:
/* 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;
}
Ho quindi compilato questi con gcc 4.1.3 su una delle mie macchine 5 volte diverse:
Ho esaminato l'output dell'assembly di ogni compilazione (usando gcc -S) e ho scoperto che in ogni caso, l'output per and.c e modulo.c erano identici (entrambi hanno usato l'istruzione andl $ 1,% eax). Dubito che questa sia una "nuova" funzionalità e sospetto che risale alle versioni antiche. Dubito anche che qualsiasi compilatore non arcano moderno (realizzato negli ultimi 20 anni), commerciale o open source, manchi di tale ottimizzazione. Vorrei testare su altri compilatori, ma al momento non ne ho a disposizione.
Se a qualcun altro piacerebbe testare altri compilatori e / o target di piattaforme e ottenere un risultato diverso, sarei molto interessato a saperlo.
Infine, la versione del modulo è garantita dallo standard per funzionare indipendentemente dal fatto che l'intero sia positivo, negativo o zero, indipendentemente dalla rappresentazione dell'implementazione degli interi con segno. La versione bit per bit non lo è. Sì, mi rendo conto che il complemento a due è un po 'onnipresente, quindi questo non è davvero un problema.
Ragazzi, siete troppo efficienti. Quello che vuoi davvero è:
public boolean isOdd(int num) {
int i = 0;
boolean odd = false;
while (i != num) {
odd = !odd;
i = i + 1;
}
return odd;
}
Ripeti per isEven.
Naturalmente, ciò non funziona per i numeri negativi. Ma con lo splendore arriva il sacrificio ...
Usa l'aritmetica dei bit:
if((x & 1) == 0)
printf("EVEN!\n");
else
printf("ODD!\n");
Questo è più veloce rispetto all'uso della divisione o del modulo.
[Modalità Joke = "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;
}
}
[Modalità Joke = "off"]
EDIT: aggiunti valori confusi all'enum.
In risposta a ffpf - ho avuto esattamente lo stesso argomento con un collega anni fa, e la risposta è no , non funziona con numeri negativi.
Lo standard C stabilisce che i numeri negativi possono essere rappresentati in 3 modi:
Verifica in questo modo:
isEven = (x & 1);
funzionerà per il complemento di 2 e la rappresentazione di segni e grandezza, ma non per il complemento di 1.
Tuttavia, credo che quanto segue funzionerà per tutti i casi:
isEven = (x & 1) ^ ((-1 & 1) | ((x < 0) ? 0 : 1)));
Grazie a ffpf per aver sottolineato che la casella di testo stava mangiando tutto dopo il mio personaggio meno che!
Una bella è:
/*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
}
Si noti che questo metodo utilizza la ricorsione della coda che coinvolge due funzioni. Può essere implementato in modo efficiente (trasformato in un po '/ fino al tipo di loop) se il tuo compilatore supporta la ricorsione della coda come un compilatore Scheme. In questo caso lo stack non dovrebbe traboccare!
Un numero è anche se, quando diviso per due, il resto è 0. Un numero è dispari se, quando diviso per 2, il resto è 1.
// Java
public static boolean isOdd(int num){
return num % 2 != 0;
}
/* C */
int isOdd(int num){
return num % 2;
}
I metodi sono fantastici!
i % 2 == 0
Direi di dividerlo per 2 e se c'è un resto 0, è pari, altrimenti è strano.
L'uso del modulo (%) lo rende facile.
per esempio. 4% 2 = 0 quindi 4 è pari al 5% 2 = 1 quindi 5 è dispari
Un'altra soluzione al problema
(i bambini sono invitati a votare)
bool isEven(unsigned int x)
{
unsigned int half1 = 0, half2 = 0;
while (x)
{
if (x) { half1++; x--; }
if (x) { half2++; x--; }
}
return half1 == half2;
}
Costruirò una tabella delle parità (0 se anche 1 se dispari) degli interi (quindi si potrebbe fare una ricerca: D), ma gcc non mi permetterà di fare matrici di tali dimensioni:
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];
}
Quindi ricorrere invece alla definizione matematica di pari e dispari.
Un numero intero n è anche se esiste un numero intero k tale che n = 2k.
Un numero intero n è dispari se esiste un numero intero k tale che n = 2k + 1.
Ecco il codice per questo:
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;
}
Consenti ai numeri C di indicare i possibili valori di intin una data compilazione C. (Si noti che C-interi è un sottoinsieme degli interi.)
Ora ci si potrebbe preoccupare che per un dato n in numeri interi C il numero intero k corrispondente potrebbe non esistere all'interno di numeri C. Ma con una piccola prova si può dimostrare che per tutti gli interi n, | n | <= | 2n | (*), dove | n | è "n se n è positivo e -n altrimenti". In altre parole, per tutte le n in numeri interi almeno una delle seguenti è valida (esattamente sia i casi (1 e 2) che i casi (3 e 4), ma non lo dimostrerò qui):
Caso 1: n <= 2n.
Caso 2: -n <= -2n.
Caso 3: -n <= 2n.
Caso 4: n <= -2n.
Ora prendi 2k = n. (Tale ak esiste se n è pari, ma non lo dimostrerò qui. Se n non è nemmeno allora il loop in evennon riesce a tornare presto comunque, quindi non importa.) Ma questo implica k <n se n non 0 per (*) e il fatto (ancora non dimostrato qui) che per tutti m, z in numeri interi 2m = z implica z non uguale a m dato m non è 0. Nel caso n è 0, 2 * 0 = 0 quindi anche 0 è fatto (se n = 0 allora 0 è in numeri interi C perché n è in numero intero C nella funzione even, quindi k = 0 è in numeri interi C). Quindi tale ak negli interi C esiste per n negli interi C se n è pari.
Un argomento simile mostra che se n è dispari, esiste ak in C-interi tale che n = 2k + 1.
Quindi le funzioni evene oddqui presentate funzioneranno correttamente per tutti gli interi C.
i % 2è molto più piccolo e probabilmente più efficiente.
%2funziona per tutti i numeri interi.
// C#
bool isEven = ((i % 2) == 0);
typedefo #defineo qualcosa del genere.
Ecco una risposta in 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();
}
Prova questo: return (((a>>1)<<1) == a)
Esempio:
a = 10101011
-----------------
a>>1 --> 01010101
a<<1 --> 10101010
b = 10011100
-----------------
b>>1 --> 01001110
b<<1 --> 10011100
Leggendo questa discussione piuttosto divertente, mi sono ricordato che avevo una funzione sensibile al tempo reale che verificava i numeri pari e dispari all'interno del ciclo principale. È una funzione di potenza intera, pubblicata altrove su StackOverflow, come segue. I benchmark sono stati abbastanza sorprendenti. Almeno in questa funzione del mondo reale, il modulo è più lento , e in modo significativo. Il vincitore, con un ampio margine, che richiede il 67% del tempo di modulo, è un approccio o (|) , e non si trova da nessuna parte in questa pagina.
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;
}
Per 300 milioni di loop, i tempi di riferimento sono i seguenti.
3.962 il | e approccio alla maschera
4.851 l'approccio &
5.850 l'approccio%
Per le persone che pensano che la teoria, o un elenco di lingue assembleari, risolva argomenti come questi, questo dovrebbe essere un ammonimento. Ci sono più cose in cielo e in terra, Orazio, di quanto si sogna nella tua filosofia.
unsigned xcome x = x >> 1;è il comportamento definito dall'implementazione quando x < 0. Non è chiaro il perché xe OrMaskdifferiscono nel tipo. Abbastanza semplice da riscrivere usando un while(x)test.
% 2caso usando bit a bit &. Ho appena provato questo e i risultati sono completamente gli stessi (VS2015, Release build con tutte le ottimizzazioni, sia x86 che x64). La risposta accettata lo afferma anche per GCC (scritto nel 2008).
orsarebbe più veloce di un andè altamente improbabile, su qualsiasi piattaforma / compilatore. Anche se ci fosse una combinazione così strana di piattaforma / compilatore (e non hai pubblicato né quello né il codice utilizzato per eseguire il benchmark), a seconda che altri compilatori si comportino allo stesso modo sarebbe una scommessa di ottimizzazione scadente. Quindi, come ho scritto, mi chiedo su quale piattaforma / compilatore sia stato testato , perché sono quasi certo che non sia stato misurato correttamente.
Questo è il seguito della discussione con @RocketRoy sulla sua risposta , ma potrebbe essere utile a chiunque desideri confrontare questi risultati.
tl; dr Da quanto ho visto, l'approccio di Roy ( (0xFFFFFFFF == (x | 0xFFFFFFFE)) non è completamente ottimizzato x & 1come modapproccio, ma in pratica i tempi di esecuzione dovrebbero risultare uguali in tutti i casi.
Quindi, per prima cosa ho confrontato l'output compilato usando Compiler Explorer :
Funzioni testate:
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 con -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 con -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
Cappelli fino a CLang, ha capito che tutti e tre i casi sono funzionalmente uguali. Tuttavia, l'approccio di Roy non è ottimizzato in GCC, quindi YMMV.
È simile con Visual Studio; ispezionando lo smontaggio Release x64 (VS2015) per queste tre funzioni, ho potuto vedere che la parte di confronto è uguale per i casi "mod" e "e" e leggermente più grande per il caso "o" di Roy:
// 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)
Tuttavia, dopo aver eseguito un benchmark effettivo per il confronto di queste tre opzioni (mod semplice, bit a bit o, bit a bit e), i risultati sono stati completamente uguali (di nuovo, Visual Studio 2005 x86 / x64, versione di rilascio, nessun debugger collegato).
L'assemblea di rilascio usa l' testistruzione per ande modcasi, mentre il caso di Roy usa l' cmp eax,0FFFFFFFFhapproccio, ma è fortemente srotolato e ottimizzato, quindi non c'è differenza nella pratica.
I miei risultati dopo 20 corse (i7 3610QM, piano di alimentazione di Windows 10 impostato su Prestazioni elevate):
[Test: Plain mod 2] TEMPO MEDIO: 689.29 ms (differenza relativa: + 0.000%) [Test: bit a bit o] TEMPO MEDIO: 689.63 ms (differenza relativa: + 0,048%) [Test: bit per bit e] TEMPO MEDIO: 687.80 ms (differenza relativa: -0.217%)
La differenza tra queste opzioni è inferiore allo 0,3%, quindi è abbastanza ovvio che l'assemblaggio è uguale in tutti i casi.
Ecco il codice se qualcuno vuole provare, con un avvertimento che ho testato solo su Windows (controlla il #if LINUXcondizionale per la get_timedefinizione e implementalo se necessario, preso da questa risposta ).
#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;
}
So che questo è solo zucchero sintattico e applicabile solo in .net ma per quanto riguarda il metodo di estensione ...
public static class RudiGroblerExtensions
{
public static bool IsOdd(this int i)
{
return ((i % 2) != 0);
}
}
Ora puoi fare quanto segue
int i = 5;
if (i.IsOdd())
{
// Do something...
}
Nella "categoria creativa ma confusa" offro:
int isOdd(int n) { return n ^ n * n ? isOdd(n * n) : n; }
Una variante di questo tema specifica per 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
}
}
Il metodo bit a bit dipende dalla rappresentazione interna dell'intero. Modulo funzionerà ovunque ci sia un operatore modulo. Ad esempio, alcuni sistemi utilizzano effettivamente i bit di basso livello per la codifica (come i linguaggi dinamici), quindi la x e 1 non funzioneranno in quel caso.
IsOdd (int x) {return true; }
Prova di correttezza: considera l'insieme di tutti i numeri interi positivi e supponi che esista un insieme non vuoto di numeri interi che non sono dispari. Poiché gli interi positivi sono ben ordinati, ci sarà un numero non dispari più piccolo, che di per sé è piuttosto dispari, quindi chiaramente quel numero non può essere nell'insieme. Pertanto, questo set non può essere non vuoto. Ripetere l'operazione per numeri interi negativi, tranne cercare il numero maggiore e non dispari.
Come alcune persone hanno pubblicato, ci sono molti modi per farlo. Secondo questo sito Web , il modo più veloce è l'operatore del modulo:
if (x % 2 == 0)
total += 1; //even number
else
total -= 1; //odd number
Tuttavia, ecco qualche altro codice che è stato contrassegnato dal banco dall'autore e che ha funzionato più lentamente dell'operazione modulo comune sopra:
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
Quante persone conoscevano persino il metodo Math.System.DivRem o perché lo avrebbero usato ??
Per dare maggiore elaborazione sul metodo dell'operatore bit a bit per quelli di noi che non hanno fatto molta algebra booleana durante i nostri studi, ecco una spiegazione. Probabilmente non serve molto all'OP, ma mi è sembrato di chiarire perché NUMBER & 1 funzionano.
Nota come quando qualcuno ha risposto sopra, il modo in cui sono rappresentati i numeri negativi può impedire a questo metodo di funzionare. In effetti, può anche rompere anche il metodo dell'operatore modulo poiché ogni lingua può differire nel modo in cui tratta gli operandi negativi.
Tuttavia, se sai che NUMBER sarà sempre positivo, questo funziona bene.
Come Tooony sopra ha sottolineato che solo l'ultima cifra in binario (e diniego) è importante.
Una porta AND logica booleana impone che entrambi gli ingressi debbano essere 1 (o alta tensione) affinché 1 venga restituito.
1 & 0 = 0.
0 & 1 = 0.
0 e 0 = 0.
1 & 1 = 1.
Se rappresenti un numero come binario (qui ho usato una rappresentazione a 8 bit), i numeri dispari hanno 1 alla fine, i numeri pari hanno 0.
Per esempio:
1 = 00000001
2 = 00000010
3 = 00000011
4 = 00000100
Se prendi un numero qualsiasi e usi AND bit a bit (e in java) per 1, restituirà 00000001, = 1, il che significa che il numero è dispari. O 00000000 = 0, il che significa che il numero è pari.
Per esempio
È dispari?
1 & 1 =
00000001 &
00000001 =
00000001 <- Dispari
2 & 1 =
00000010 &
00000001 =
00000000 <- Pari
54 & 1 =
00000001 &
00110110 =
00000000 <- Pari
Ecco perché funziona:
if(number & 1){
//Number is odd
} else {
//Number is even
}
Scusate se questo è ridondante.
Parità Numero Zero | zero http://tinyurl.com/oexhr3k
Sequenza di codici 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))
Produzione:
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);
}
Per motivi di discussione ...
Hai solo bisogno di guardare l'ultima cifra in un dato numero per vedere se è pari o dispari. Firmati, non firmati, positivi, negativi - sono tutti uguali per quanto riguarda questo. Quindi questo dovrebbe funzionare a tutto tondo: -
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 chiave qui è nella terza riga di codice, l'operatore di divisione esegue una divisione intera, in modo che al risultato manchi la parte della frazione del risultato. Quindi, ad esempio, 222/10 darà 22 di conseguenza. Quindi moltiplicalo di nuovo per 10 e hai 220. Sottrai quello dal 222 originale e finisci con 2, che per magia è lo stesso numero dell'ultima cifra del numero originale. ;-) Le parentesi sono lì per ricordarci l'ordine in cui viene eseguito il calcolo. Prima fai la divisione e la moltiplicazione, quindi sottrai il risultato dal numero originale. Potremmo lasciarli fuori, poiché la priorità è più alta per la divisione e la moltiplicazione che per la sottrazione, ma questo ci dà un codice "più leggibile".
Potremmo renderlo completamente illeggibile se volessimo. Non farebbe alcuna differenza per un compilatore moderno: -
printf("%d%s\n",iToTest,0==(iToTest-iToTest/10*10)%2?" is even":" is odd");
Ma renderebbe il codice molto più difficile da mantenere in futuro. Immagina di voler cambiare il testo per i numeri dispari in "non è pari". Quindi qualcun altro in seguito vorrà scoprire quali modifiche sono state apportate ed eseguire un svn diff o simile ...
Se non sei preoccupato per la portabilità ma più per la velocità, potresti dare un'occhiata al bit meno significativo. Se quel bit è impostato su 1 è un numero dispari, se è 0 è un numero pari. Su un piccolo sistema endian, come l'architettura x86 di Intel, sarebbe qualcosa del genere: -
if (iToTest & 1) {
// Even
} else {
// Odd
}
Se vuoi essere efficiente, usa operatori bit per bit ( x & 1), ma se vuoi essere leggibile usa modulo 2 ( x % 2)
%. Se vuoi che sia leggibile, usa %. Hmmm, vedo uno schema qui.
Il controllo di pari o dispari è un compito semplice.
Sappiamo che qualsiasi numero esattamente divisibile per 2 è pari al numero dispari.
Dobbiamo solo verificare la divisibilità di qualsiasi numero e per verificare la divisibilità che usiamo % operatore
Controllo dispari usando se altrimenti
if(num%2 ==0)
{
printf("Even");
}
else
{
printf("Odd");
}
Programma C per controllare se pari o dispari usando altrimenti
Utilizzo dell'operatore Condizionale / Ternario
(num%2 ==0) printf("Even") : printf("Odd");
Programma C per controllare pari o dispari usando l'operatore condizionale .
Utilizzo dell'operatore Bitwise
if(num & 1)
{
printf("Odd");
}
else
{
printf("Even");
}
!(i%2) / i%2 == 0int isOdd(int n)
{
return n & 1;
}
Il codice controlla l'ultimo bit dell'intero se è 1 in binario
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...
Si noti che il bit più a destra è sempre 1 per i numeri dispari .
i & bit per bit AND operatore controlla il bit più a destra nel nostro ritorno linea se si tratta di 1
Quando confrontiamo n con 1 che significa 0001in binario (il numero di zeri non ha importanza).
allora immaginiamo di avere l'intero n con una dimensione di 1 byte.
Sarebbe rappresentato da cifre a 8 bit / 8 binarie.
Se int n era 7 e lo confrontiamo con 1 , è come
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
Quale F sta per falso e T per vero.
Esso mette a confronto solo il bit più a destra se sono entrambe vere. Quindi, automagicamente
7 & 1è T rue.
Passa semplicemente n & 1a n & 22 che rappresenta0010 in binario e così via.
Ti suggerisco di usare la notazione esadecimale se sei un principiante alle operazioni bit per bit
return n & 1;>> return n & 0x01;.