Wie kann ich überprüfen, ob eine ganze Zahl gerade oder ungerade ist? [geschlossen]

StackOverflow https://stackoverflow.com/questions/160930

  •  03-07-2019
  •  | 
  •  

Frage

Wie kann ich überprüfen, ob eine gegebene Zahl gerade oder ungerade ist in C?

War es hilfreich?

Lösung

den Modulo-Operator (%) können Sie prüfen, ob ein Rest ist, wenn sie durch 2 dividiert:

if (x % 2) { /* x is odd */ }

Ein paar Leute haben meine Antwort oben besagt, kritisiert, dass x & 1 verwendet, ist „schneller“ oder „effizienter“. Ich glaube nicht, dass dies der Fall sein.

Aus Neugier, habe ich zwei trivialen Testfall Programme:

/* 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;
}

ich kompiliert diese dann mit gcc 4.1.3 auf einem meiner Rechner 5 verschiedenen Zeiten:

  • Ohne Optimierungen.
  • Mit -O
  • Mit -Os
  • Mit -O2
  • Mit O3

Ich untersuchte die Baugruppe Ausgang jedes der Kompilierung (gcc -S verwenden) und festgestellt, dass der Ausgang für and.c modulo.c und in jedem Fall waren identisch (sie verwendet, um sowohl die andl $ 1,% eax-Befehl). Ich bezweifle, dass dies ein „neues“ Feature ist, und ich vermute, es stammt aus alten Versionen. Ich habe auch jede moderne Zweifel (hergestellt in den letzten 20 Jahren) nicht-arkanen Compiler, kommerzielle oder Open Source, fehlt eine solche Optimierung. Ich würde auf anderen Compilern testen, aber ich habe keine verfügbar im Moment.

Wenn jemand anderen Compilern und / oder Plattform Ziele zu testen kümmern würde, und bekommt ein anderes Ergebnis, würde ich sehr daran interessiert zu wissen.

Schließlich ist die Modulo-Version garantiert durch den Standard zu arbeiten, ob die ganze Zahl ist positiv, negativ oder Null ist, unabhängig von der Vertretung der Umsetzung der unterzeichneten Zahlen. Die bitweise-und-Version ist es nicht. Ja, ich merke, Zweier-Komplement etwas allgegenwärtig ist, so ist dies nicht wirklich ein Problem.

Andere Tipps

Ihr seid waaaaaaaay zu effizient. Was Sie wirklich wollen, ist:

public boolean isOdd(int num) {
  int i = 0;
  boolean odd = false;

  while (i != num) {
    odd = !odd;
    i = i + 1;
  }

  return odd;
}

Wiederholen Sie für isEven.

Natürlich, die nicht für negative Zahlen funktioniert. Aber mit Brillanz kommt Opfer ...

Verwenden Bit-Arithmetik:

if((x & 1) == 0)
    printf("EVEN!\n");
else
    printf("ODD!\n");

Dies ist schneller als die Verwendung von Teilung oder Modul.

[Joke mode = "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;
  }
}

[Joke mode = "off"]

EDIT:. Hinzugefügt verwirrend Werte der Enum

Als Reaktion auf ffpf -. ich hatte genau das gleiche Argument mit einem Kollegen vor einigen Jahren, und die Antwort ist nein , ist es nicht mit negativen Zahlen arbeitet

Der C-Standard schreibt vor, dass negative Zahlen können auf 3 Arten dargestellt werden:

  • 2-Komplement
  • 1-Komplement
  • Vorzeichen und Größe

wie folgt prüfen:

isEven = (x & 1);

für 2-Komplement arbeitet und unterschreiben und Größendarstellung, aber nicht für 1-Komplement.

Ich glaube jedoch, daß für alle Fälle funktioniert:

isEven = (x & 1) ^ ((-1 & 1) | ((x < 0) ? 0 : 1)));

Danke für den Hinweis auf ffpf dass das Textfeld alles nach meinem weniger als Charakter zu essen war!

Ein schöner ist:

/*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
}

Beachten Sie, dass diese Methode verwenden Endrekursion mit zwei Funktionen. Es kann effizient implementiert werden (in eine Zeit lang / bis Art von Schleife gedreht), wenn Ihr Compiler Endrekursion wie ein Schema Compiler unterstützt. In diesem Fall sollte der Stapel nicht überlaufen!

Eine Zahl wird auch dann, wenn, wenn sie durch zwei geteilt, der Rest ist 0. Eine Anzahl ungerade ist, wenn, wenn sie durch 2 geteilt, wobei der Rest 1 ist.

// Java
public static boolean isOdd(int num){
    return num % 2 != 0;
}

/* C */
int isOdd(int num){
    return num % 2;
}

Methoden sind groß!

i % 2 == 0

Ich würde sagen, es einfach Teile durch 2 und wenn es einen 0 Rest ist, ist es noch, sonst ist es seltsam.

Mit dem Modul (%) macht dies einfach.

zB. 4% 2 = 0 daher 4 sogar 5% 2 = 1 5 daher ungerade

Eine weitere Lösung für das Problem
(Kinder sind willkommen zu stimmen)

bool isEven(unsigned int x)
{
  unsigned int half1 = 0, half2 = 0;
  while (x)
  {
     if (x) { half1++; x--; }
     if (x) { half2++; x--; }

  }
  return half1 == half2;
}

würde ich eine Tabelle der Paritäten (0, wenn auch 1, wenn ungerade) der ganzen Zahlen bauen (so könnte man einen Nachschlag tun: D), aber gcc lässt mich nicht Arrays solcher Größen machen:

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];
}

Also lassen Sie sich stattdessen auf die mathematische Definition greift von geraden und ungeraden statt.

Eine ganze Zahl n ist, selbst wenn es vorhanden ist eine ganze Zahl k, so daß n = 2k.

Eine Ganzzahl n ungerade ist, wenn es eine ganze Zahl k existiert, so dass n = 2k + 1.

Hier ist der Code für sie:

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;
}

Lassen Sie C-Zahlen die möglichen Werte von int in einer gegebenen C Zusammenstellung bezeichnen. (Beachten Sie, dass C-Zahlen eine Teilmenge der ganzen Zahlen ist.)

Nun könnte man befürchten, dass für ein gegebenes n in C-Zahlen, die die entsprechende Zahl k kann nicht innerhalb von C-Zahlen existieren. Aber mit einem wenig Beweis ist, kann es, dass für alle ganzen Zahlen n angezeigt, | n | <= | 2n | (*), Wobei | n | „n, wenn n positiv und -n sonst“. Mit anderen Worten, für all n in ganzen Zahlen mindestens eine der folgenden hält (genau beiden Fälle (1 und 2) oder Fälle (3 und 4) in der Tat, aber ich werde es hier nicht beweisen):

Fall 1:. N <= 2n

Fall 2:. -N <= -2n

Fall 3:. -N <= 2n

Case. 4: n <= -2n

Nehmen Sie nun 2k = n. (Ein solche ak existieren, wenn n gerade ist, aber ich werde es hier nicht beweisen. Wenn n nicht einmal dann die Schleife in even nicht früh sowieso zurück, so dass es keine Rolle spielt.) Aber dies bedeutet, k even ist daher k = 0 ist, in C-Zahlen). So ein solches k in C-Zahlen existiert für n in C-Zahlen, wenn n gerade ist.

Ein ähnliches Argument zeigt, daß, wenn n ungerade ist, gibt es eine k in C-Zahlen, so besteht, daß n = 2k + 1.

Daraus ergibt sich die Funktionen even und odd hier präsentiert wird richtig für alle C-Zahlen arbeiten.

// C#
bool isEven = ((i % 2) == 0);

Hier ist eine Antwort 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();
}

Versuchen Sie diese: return (((a>>1)<<1) == a)

Beispiel:

a     =  10101011
-----------------
a>>1 --> 01010101
a<<1 --> 10101010

b     =  10011100
-----------------
b>>1 --> 01001110
b<<1 --> 10011100

Mit dieser eher unterhaltsam Diskussion Lesen, erinnerte ich mich, dass ich eine reale, zeitkritische Funktion hatte, die für gerade und ungerade Zahlen innerhalb der Hauptschleife getestet. Es ist eine ganze Zahl Potenzfunktion, geschrieben an anderer Stelle auf Stackoverflow, wie folgt. Die Benchmarks war ziemlich überraschend. Zumindest in dieser realen Welt Funktion Modulo ist langsamer , und so deutlich. Der Gewinner, mit großem Abstand, erfordert 67% der Zeit des Modulo, ist ein oder (|) Ansatz , und ist unauffindbar auf dieser Seite an anderer Stelle zu sein.

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;
}

Für 300 Millionen Schleifen sind die Benchmark-Timings wie folgt.

3,962 die | und Maske Ansatz

4.851 der & Ansatz

5,850% der Ansatz

Für Menschen, die Theorie denken, oder eine Auflistung der Assemblersprache, setzt Argumente wie diese, sollte dies ein warnendes Beispiel sein. Es gibt mehr Dinge im Himmel und Erde, Horatio, als in unserer Philosophie geträumt werden.

Dies ist eine der Diskussion folgt mit @RocketRoy in Bezug auf seine Antwort , aber es könnte für jeden nützlich sein, will diese Ergebnisse vergleichen.

tl; DR. Von dem, was ich gesehen habe, Roy Ansatz ((0xFFFFFFFF == (x | 0xFFFFFFFE)) nicht vollständig als x & 1 Ansatz mod optimiert, aber in der Praxis Laufzeiten sollten in allen Fällen gleich ausfallen

Also, zuerst verglich ich die kompilierte Ausgabe mit Compiler Explorer :

Funktionen getestet:

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 mit 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 mit 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

Hüte bis zu klappern, erkannte er, dass alle drei Fälle funktionell gleich sind. Allerdings ist Roys Ansatz nicht in GCC optimiert, so YMMV.

Es ist ähnlich mit Visual Studio; finden Sie in der Demontage Veröffentlichung x64 (VS2015) für diese drei Funktionen Inspektion, konnte ich, dass der Vergleichsteil für „mod“ gleich ist und „und“ Fälle, und etwas größer für die Roys „oder“ Fall:

// 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)

Nachdem jedoch für eine tatsächliche Benchmark laufen diese drei Optionen (Plain mod, bit- oder, bitweise und) zu vergleichen, die Ergebnisse waren völlig gleich (wieder, Visual Studio 2005 x86 / x64, Releasebuild, kein Debugger angeschlossen).

Veröffentlichungs Montage verwendet die test Anweisung für and und mod Fälle, während Roy Fall die cmp eax,0FFFFFFFFh Ansatz verwendet, aber es ist schwer abgerollt und optimiert, so gibt es keinen Unterschied in der Praxis ist.

Meine Ergebnisse nach 20 Läufen (i7 3610QM, Windows-10 Energiesparplan auf High Performance):

[Test: Plain mod 2 ] AVERAGE TIME: 689.29 ms (Relative diff.: +0.000%)
[Test: Bitwise or  ] AVERAGE TIME: 689.63 ms (Relative diff.: +0.048%)
[Test: Bitwise and ] AVERAGE TIME: 687.80 ms (Relative diff.: -0.217%)

Der Unterschied zwischen diesen Optionen ist weniger als 0,3%, so ist es ziemlich offensichtlich, die Montage in allen Fällen gleich ist.

Hier ist der Code, wenn jemand will, mit einem Vorbehalt versuchen, dass ich es nur auf Windows getestet (siehe Info #if LINUX bedingte für die get_time Definition und umzusetzen, wenn nötig, genommen von diese Antwort ).

#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;
}

Ich weiß, das nur syntaktischer Zucker ist und nur anwendbar in .net , aber was Erweiterungsmethode ...

public static class RudiGroblerExtensions
{
    public static bool IsOdd(this int i)
    {
        return ((i % 2) != 0);
    }
}

Jetzt können Sie die folgenden Aktionen

int i = 5;
if (i.IsOdd())
{
    // Do something...
}

In der "kreativ, aber verwirrend Kategorie" Ich biete:

int isOdd(int n) { return n ^ n * n ? isOdd(n * n) : n; }

Eine Variante dieses Thema, das zu Microsoft C ++ spezifisch ist:

__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
    }
}

bitweisen Die Methode hängt von der inneren Darstellung der ganzen Zahl. Modulo wird überall dort arbeiten, ist ein Modulo-Operator. Zum Beispiel verwenden einige Systeme tatsächlich den niedrigen Pegel Bits für Tagging (wie dynamische Sprachen), so dass die rohen x & 1 wird nicht wirklich in diesem Fall arbeiten.

IsOdd (int x) {return true; }

Der Nachweis der Korrektheit - die Menge aller positiven ganzen Zahlen betrachten, und es nehme eine nicht leere Menge der ganzen Zahlen ist, die nicht ungerade sind. Da positive ganze Zahlen sind gut bestellt, wird es eine kleinste nicht ungerade Zahl sein, die an sich ziemlich merkwürdig ist, so deutlich, dass Zahl nicht in der Menge sein kann. Daher kann dieser Satz nicht nicht leer sein. Wiederholen Sie dies für negative ganze Zahlen außer Look für die größte nicht ungerade Zahl ist.

Portable:

i % 2 ? odd : even;

unportable:

i & 1 ? odd : even;

i << (BITS_PER_INT - 1) ? odd : even;

Wie einige Leute geschrieben haben, gibt es zahlreiche Möglichkeiten, dies zu tun. Nach diese Website , der schnellste Weg ist der Modulo-Operator:

if (x % 2 == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

Allerdings ist hier einige anderer Code, die Bank war gekennzeichnet durch den Autor die oben langsamer als der gemeinsame Modul Betrieb lief:

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

Wie viele Menschen wussten auch die Math.System.DivRem Methode oder warum sollten sie es verwenden ??

int isOdd(int i){
  return(i % 2);
}

getan.

Für weitere Ausarbeitung auf der Bit-Operator-Methode für das von uns zu geben, die nicht viel Boolesche Algebra zu tun haben während unserer Studien hier ist eine Erklärung. Wahrscheinlich nicht viel zum OP, aber ich habe das Gefühl, es klar, warum NUMBER & 1 Werken zu machen.

Bitte beachten Sie, wie jemand wie oben beantwortet, die Art und Weise negative Zahlen dargestellt werden, können Sie diese Methode mehr funktionieren. In der Tat kann es sogar die Modulo-Operator-Methode brechen, da jede Sprache in unterschiedlich sein können, wie es befasst sich mit negativen Operanden.

Wenn Sie jedoch, dass NUMBER wissen immer positiv sein wird, das funktioniert gut.

Wie Tooony oben wies darauf hin, dass nur die letzte Ziffer in binären (und denary) wichtig ist.

A Booleschen logische UND-Gatter vor, dass beiden Eingänge haben eine 1 (oder Hochspannung) sein, um nach 1 zurückgeführt werden.

1 & 0 = 0 ist.

0 & 1 = 0

0 0 = 0 ist.

1 & 1 = 1.

Wenn Sie eine beliebige Anzahl als binäre repräsentieren (ich habe eine 8-Bit-Darstellung hier verwendet wird), ungerade Zahlen 1 am Ende, auch Zahlen 0 haben.

Zum Beispiel:

1 = 00000001

2 = 00000010

3 = 00000011

4 = 00000100

Wenn Sie eine beliebige Anzahl und Verwendung bitweise nehmen AND (& in Java) um 1 wird es entweder zurückgeben 00000001 = 1 bedeutet die Zahl ungerade ist. Oder 00000000 = 0, die Zahl und bedeutet auch.

Z. B

Ist ungerade?

1 & 1 =

00000001 &

00000001 =

00000001 <- Odd

2 & 1 =

00000010 &

00000001 =

00000000 <- Selbst

54 & 1 =

00000001 &

00110110 =

00000000 <- Selbst

Dies ist, warum dies funktioniert:

if(number & 1){

   //Number is odd

} else {

   //Number is even
}

Sorry, wenn dies redundant ist.

Zahl Null Parität | Null http://tinyurl.com/oexhr3k

Python-Code-Sequenz.

# 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))
  

Ausgang:

   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);
}

Aus Gründen der Diskussion ...

Sie müssen nur an der letzten Stelle in einer bestimmten Nummer suchen, um zu sehen, ob es gerade oder ungerade ist. Signed, ohne Vorzeichen, positiv, negativ - sie sind alle gleich in Bezug auf diese. So sollte diese Arbeit rundum: -

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);
  }
}

hier der Schlüssel in der dritten Zeile des Codes ist, führt der Bediener eine Teilungs Integer-Division, so dass aufgrund des Bruchteil des Ergebnisses fehlen. So zum Beispiel 222/10 werden 22 als Ergebnis. Dann multiplizieren Sie es wieder mit 10 und Sie haben 220 subtrahieren, dass aus den ursprünglichen 222 und Sie mit 2 am Ende, die durch Magie die gleiche Nummer wie die letzte Ziffer in der ursprünglichen Zahl ist. ;-) Die Klammer ist da, um uns von der Reihenfolge zu erinnern, wird die Berechnung erfolgt in. Zuerst die Trennung tun und die Multiplikation, dann das Ergebnis aus der ursprünglichen Zahl subtrahieren. Wir können sie auslassen, da die höhere Priorität für die Division und Multiplikation als der Subtraktion, aber das gibt wir „lesbaren“ Code.

Wir konnten machen es völlig unleserlich, wenn wir wollten. Es würde keinen Unterschied machen, was auch immer für einen modernen Compiler: -

printf("%d%s\n",iToTest,0==(iToTest-iToTest/10*10)%2?" is even":" is odd");

Aber es wäre der Code Art und Weise schwieriger zu pflegen in der Zukunft machen. Man stelle sich vor, dass Sie den Text für ungerade Zahlen ändern möchte „ist nicht einmal“. Dann jemand anderes später wollen herausfinden, welche Änderungen Sie gemacht und führen Sie eine svn diff oder ähnliches ...

Wenn Sie nicht besorgt über Portabilität sind aber mehr über die Geschwindigkeit, können Sie einen Blick auf dem am wenigsten signifikanten Bit haben. Wenn dieses Bit auf 1 gesetzt ist, ist es eine ungerade Zahl, wenn es 0 ist, es ist eine gerade Zahl. Auf einem kleinen Endian-System, wie Intels x86-Architektur wäre es so etwas wie dieses: -

if (iToTest & 1) {
  // Even
} else {
  // Odd
}

Wenn Sie effizient sein möchten, verwenden Sie bitweise Operatoren (x & 1), aber wenn Sie wollen lesbar Verwendung Modulo 2 (x % 2)

sein

Überprüfen gerade oder ungerade ist eine einfache Aufgabe.

  

Wir wissen, dass jede Zahl genau durch 2 teilbar ist gerade Zahl sonst ungerade.

Wir brauchen nur die Teilbarkeit von einer beliebigen Anzahl zu überprüfen und zur Überprüfung Teilbarkeit verwenden wir % Operator

Überprüfen sogar ungerade verwenden, wenn sonst

if(num%2 ==0)  
{
    printf("Even");
}
else
{
    printf("Odd");
}

C-Programm zu überprüfen gerade oder ungerade zu verwenden, wenn sonst

Verwendung bedingter / Ternary Operator

(num%2 ==0) printf("Even") : printf("Odd");

C Programm überprüfen gerade oder ungerade mit Konditionaloperator .

Mit bitweise Operator

if(num & 1)  
{
    printf("Odd");
}
else 
{
    printf("Even");
}

+66% schneller> !(i%2) / i%2 == 0

int isOdd(int n)
{
    return n & 1;
}

Der Code überprüft das letzte Bit der ganzen Zahl, wenn es 1 in Binary

Erklärung

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...
  

Hinweis die rechte Bit ist immer 1 für Odd Zahlen.

& bitweise AND-Operator prüft das Bit ganz rechts in unserem zurück Zeile, wenn es 1
ist

Denken Sie an es als true & false

Wenn wir vergleichen n mit 1 , die 0001 in binärer bedeutet (Anzahl der Nullen spielt keine Rolle).
dann lassen Sie sich nur vorstellen, dass wir die ganze Zahl n mit einer Größe von 1 Byte haben.

Es wäre von 8-Bit / 8-Binärzahlen dargestellt werden.

Wenn der int n war 7 und wir vergleichen es mit 1 , Es ist wie

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

Welche F steht für falsch und T für wahr.

  

Es vergleicht nur das Bit ganz rechts, wenn sie beide wahr sind. Also, automagically 7 & 1 ist T rue.

Was passiert, wenn ich das Bit vor dem ganz rechts überprüfen möchten?

Einfach n & 1 ändern n & 2 die 2 0010 in Binary darstellt und so weiter.

Ich schlage vor, mit hexadezimale Schreibweise, wenn Sie ein Anfänger sind Operationen bitweise
return n & 1; >> return n & 0x01;.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top