정수가 균일한지 또는 홀수인지 어떻게 확인합니까? [닫은

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

  •  03-07-2019
  •  | 
  •  

문제

C에서 주어진 숫자가 균일한지 또는 홀수인지 어떻게 확인할 수 있습니까?

도움이 되었습니까?

해결책

모듈로 (%) 연산자를 사용하여 2로 나눌 때 나머지가 있는지 확인하십시오.

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

몇몇 사람들은 X & 1을 사용하는 것이 "빠르거나"더 효율적 "이라는 내 대답을 비판했습니다. 나는 이것이 사실이라고 믿지 않는다.

호기심으로, 나는 두 가지 사소한 시험 사례 프로그램을 만들었습니다.

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

그런 다음 컴퓨터 중 하나에서 GCC 4.1.3으로 5 번을 컴파일했습니다.

  • 최적화 플래그가 없습니다.
  • -O와 함께
  • -os와 함께
  • -O2로
  • -O3로

나는 각 컴파일의 어셈블리 출력 (GCC -S를 사용)을 검사 한 결과 각각의 경우 및.c 및 modulo.c의 출력이 동일하다는 것을 발견했습니다 (둘 다 AND $ 1, %EAX 명령어를 사용했습니다). 나는 이것이 "새로운"기능이라고 의심하며, 그것이 고대 버전으로 거슬러 올라간 것으로 생각합니다. 또한 현대 (지난 20 년 동안) 비 아케인 컴파일러, 상용 또는 오픈 소스는 그러한 최적화가 부족하다고 의심합니다. 다른 컴파일러를 테스트하지만 현재 사용할 수있는 것은 없습니다.

다른 사람이 다른 컴파일러 및/또는 플랫폼 대상을 테스트하고 다른 결과를 얻는다면 알고 싶습니다.

마지막으로 모듈로 버전은입니다 보장 표준에 따라 정수가 서명 된 정수의 구현의 표현에 관계없이 정수가 양수, 음수 또는 0인지 여부에 따라 작동합니다. 비트와 버전은 아닙니다. 그렇습니다. 나는 둘의 보완이 다소 유비쿼터스라는 것을 알고 있으므로 이것이 실제로 문제가되지 않습니다.

다른 팁

너희들은 너무 효율적이다. 당신이 정말로 원하는 것은 :

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

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

  return odd;
}

반복하십시오 isEven.

물론, 그것은 음수에 대해서는 효과가 없습니다. 그러나 광채로 희생이 온다 ...

비트 산술 사용 :

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

이것은 분할 또는 모듈러스를 사용하는 것보다 빠릅니다.

농담 모드 = "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;
  }
}

농담 모드 = "꺼짐"

편집 : 열거에 혼란스러운 값을 추가했습니다.

응답으로 FFPF - 몇 년 전 동료와 똑같은 주장을했는데 그 대답은 아니요, 그것은 음수로 작동하지 않습니다.

C 표준은 음수가 3 가지 방식으로 표현 될 수 있음을 규정합니다.

  • 2의 보완
  • 1의 보완
  • 표시와 크기

이렇게 확인 :

isEven = (x & 1);

2의 보완 및 부호 및 크기 표현에는 효과가 있지만 1의 보완에는 효과가 없습니다.

그러나 다음은 모든 경우에 효과가 있다고 생각합니다.

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

텍스트 상자가 내 캐릭터보다 덜 먹은 후 모든 것을 먹었다는 것을 지적한 FFPF에게 감사합니다!

좋은 것은 다음과 같습니다.

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

이 방법은 두 가지 함수와 관련된 꼬리 재귀를 사용합니다. 컴파일러가 체계 컴파일러처럼 꼬리 재귀를 지원하는 경우 효율적으로 구현할 수 있습니다 (루프가 끝날 때까지). 이 경우 스택은 오버플로가되어서는 안됩니다!

숫자는 2로 나뉘어 질 때 나머지가 0이더라도 숫자는 0입니다.

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

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

방법은 훌륭합니다!

i % 2 == 0

나는 단지 그것을 2로 나눕니다. 그리고 나머지가 0 인 경우, 심지어는 홀수입니다.

모듈러스 (%)를 사용하면 쉽게 만듭니다.

예를 들어. 4 % 2 = 0이므로 4는 5 % 2 = 1이므로 5는 홀수입니다.

문제에 대한 하나의 솔루션
(어린이는 투표를 환영합니다)

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

  }
  return half1 == half2;
}

정수의 패리티 테이블 (홀수 인 경우 1 인 경우 0)을 구축 할 것입니다 (따라서 조회를 할 수 있습니다 : D).

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

대신 짝수와 홀수의 수학적 정의에 의지하자.

정수 n은 n = 2k와 같은 정수 k가 존재하더라도입니다.

정수 n은 n = 2k + 1이되는 정수 k가있는 경우 홀수입니다.

다음은 코드입니다.

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

C-Integers가 가능한 값을 나타냅니다 int 주어진 C 컴파일에서. (C-Integers는 정수의 하위 집합입니다.)

이제 C-Integers의 주어진 N에 대해 해당 정수 K가 C- 인테르에 존재하지 않을 것이라고 걱정할 수 있습니다. 그러나 약간의 증거로 모든 정수 n에 대해 n, | n | <= | 2n | (*), 여기서 | n | "n이 양수이고 그렇지 않으면 -n"입니다. 다시 말해, 정수의 모든 N에 대해 다음 중 적어도 하나는 다음 중 하나 이상 (정확히 1 및 2) 또는 사례 (3 및 4)를 실제로 증명하지는 않습니다.

사례 1 : n <= 2n.

사례 2 : -n <= -2n.

사례 3 : -n <= 2n.

사례 4 : n <= -2n.

이제 2k = n을 가져갑니다. (그러한 AK는 N이라면 존재하지만 여기서 증명하지는 않을 것입니다. N이면 심지어 루프가 even 어쨌든 일찍 돌아 오지 않으므로 중요하지 않습니다.) 그러나 이것은 0에 의해 0이 아닌 경우 k <n을 의미합니다. M과 동일하지 않은 M은 0이 아닙니다. 경우 N은 0, 2*0 = 0이므로 0은 우리가 완료됩니다 (N = 0이면 0이 C-Integer에있는 경우 N = 0이면 N이 기능 even, 따라서 k = 0은 c-integers에 있습니다). 따라서, C- 인테르의 AK는 N이라도 C- 인테르에 N에 대해 존재한다.

비슷한 인수는 n이 홀수 인 경우 c-integers에 n = 2k + 1과 같은 Ak가 존재한다는 것을 보여준다.

따라서 기능 even 그리고 odd 여기에 제시된 것은 모든 C- 인테르 에스에게 제대로 작동합니다.

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

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

이 시도: return (((a>>1)<<1) == a)

예시:

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

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

이 재미있는 토론을 읽었을 때, 나는 메인 루프 내부의 홀수 및 짝수 숫자를 테스트 한 실제 시간에 민감한 기능이 있다는 것을 기억했습니다. 다음과 같이 StackoverFlow에 다른 곳에 게시 된 정수 파워 함수입니다. 벤치 마크는 매우 놀랍습니다. 적어도이 실제 기능에서 모듈로는 느립니다, 그리고 심각하게. 모듈로 시대의 67%를 요구하는 넓은 마진으로 승자는 또는 (|) 접근법입니다., 이 페이지의 다른 곳에서는 찾을 수 없습니다.

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

3 억 루프의 경우 벤치 마크 타이밍은 다음과 같습니다.

3.962 | 그리고 마스크 접근

4.851 & 접근

5.850 % 접근법

이론이나 어셈블리 언어 목록을 생각하는 사람들에게는 이와 같은 논쟁을 해결합니다. 이것은주의해야 할 이야기가되어야합니다. 하늘과 땅, 호라 티오에는 당신의 철학에서 꿈꾸는 것보다 더 많은 것들이 있습니다.

이것은 @rocketroy와의 토론에 대한 후속 조치입니다. 그의 대답, 그러나이 결과를 비교하려는 사람에게는 유용 할 수 있습니다.

tl; dr 내가 본 것에서 Roy의 접근 방식 ((0xFFFFFFFF == (x | 0xFFFFFFFE))는 완전히 최적화되지 않습니다 x & 1 로서 mod 접근 방식이지만 실제로 실행 시간은 모든 경우에 동일하게 나타납니다.

따라서 먼저 컴파일 된 출력을 사용하여 비교했습니다 컴파일러 탐색기:

테스트 된 기능 :

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

-o3가있는 Clang 3.9.0 :

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

-o3 인 GCC 6.2 :

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

Clang까지 모자를 내면서 세 가지 사례가 모두 기능적으로 동일하다는 것을 깨달았습니다. 그러나 Roy의 접근 방식은 GCC에서 최적화되지 않았으므로 YMMV.

Visual Studio와 비슷합니다. 이 세 가지 함수에 대해 분해 릴리스 X64 (vs2015)를 검사하면 비교 부분이 "mod"및 "and"cases와 같고 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)

그러나이 세 가지 옵션 (Plain Mod, Bitwise 또는 Bitwise 및)을 비교하기위한 실제 벤치 마크를 실행 한 후 결과는 완전히 동일했습니다 (다시, Visual Studio 2005 x86/x64, 릴리스 빌드, 디버거가 첨부되지 않음).

릴리스 어셈블리를 사용합니다 test 에 대한 지시 and 그리고 mod Roy의 사례는 다음을 사용합니다 cmp eax,0FFFFFFFFh 접근 방식이지만 무너지고 최적화되어 실제로 차이가 없습니다.

20 번의 실행 후 결과 (i7 3610QM, Windows 10 전원 계획이 고성능으로 설정 됨) :

[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%)

이러한 옵션의 차이는 0.3%미만이므로 모든 경우 어셈블리가 동일하다는 것이 분명합니다.

누군가가 시도하고 싶다면 코드는 다음과 같습니다. Windows에서만 테스트 한 경고가 있습니다 (확인하십시오. #if LINUX 조건부 get_time 필요에 따라 정의하고 구현하십시오 이 답변).

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

나는 이것이 단지 구문 설탕이라는 것을 알고 있습니다 .NET에만 적용됩니다 그러나 확장 방법은 어떻습니까 ...

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

이제 다음을 수행 할 수 있습니다

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

"창의적이지만 혼란스러운 카테고리"에서 나는 다음을 제안한다.

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

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

비트 방법은 정수의 내부 표현에 따라 다릅니다. 모듈로는 모듈로 연산자가있는 곳 어디에서나 작동합니다. 예를 들어, 일부 시스템은 실제로 태깅에 낮은 레벨 비트를 사용하여 (동적 언어와 같은) RAW X & 1은 실제로 작동하지 않습니다.

isodd (int x) {return true; }

정확성 증명 - 모든 양의 정수 세트를 고려하고 이상하지 않은 정수 세트가 있다고 가정하십시오. 양수 정수가 잘 정렬되어 있기 때문에 홀수가 가장 적지 않을 것입니다. 그 자체로는 꽤 이상하므로 분명히 그 숫자는 세트에있을 수 없습니다. 따라서이 세트는 비어 있지 않을 수 없습니다. 가장 큰 홀수를 찾는 것을 제외하고는 음의 정수를 반복하십시오.

가지고 다닐 수 있는:

i % 2 ? odd : even;

보장 할 수 없음 :

i & 1 ? odd : even;

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

어떤 사람들이 게시 한 것처럼, 이것을하는 방법에는 여러 가지가 있습니다. 에 따르면 이 웹 사이트, 가장 빠른 방법은 모듈러스 연산자입니다.

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

그러나 여기에 일부가 있습니다 벤치가 표시된 다른 코드 위의 일반적인 모듈러스 작업보다 느린 저자에 의해 :

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

얼마나 많은 사람들이 Math.System.divrem 방법이나 왜 그것을 사용합니까?

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

완료.

연구 중에 부울 대수학을 많이하지 않은 사람들을 위해 Bitwise Operator 방법에 대해 더 자세히 설명하기 위해 설명이 있습니다. 아마도 OP에 많이 사용되지는 않지만 숫자와 1이 왜 작동하는지 명확하게 생각하는 느낌이 들었습니다.

위의 누군가가 위의 대답과 마찬가지로 음수가 표현되는 방식은이 방법이 작동하지 않을 수 있습니다. 실제로 각 언어는 마이너스 피연산자를 다루는 방식이 다를 수 있기 때문에 모듈로 연산자 방법을 깨뜨릴 수도 있습니다.

그러나 숫자가 항상 긍정적이라는 것을 알고 있다면 이것은 잘 작동합니다.

위의 너무 많은 것은 바이너리 (및 거부)의 마지막 숫자 만 중요하다는 점을 지적했습니다.

부울 로직과 게이트는 두 입력 모두 1을 반환하려면 1 (또는 고전압)이어야한다고 지시합니다.

1 & 0 = 0.

0 & 1 = 0.

0 & 0 = 0.

1 & 1 = 1.

숫자를 바이너리로 나타내는 경우 (여기서 8 비트 표현을 사용했습니다), 홀수는 끝에 1이 1이고 숫자는 0이됩니다.

예를 들어:

1 = 00000001

2 = 00000010

3 = 00000011

4 = 00000100

숫자를 가져 와서 비트를 사용하고 (& java) 1 씩 사용하면 00000001을 반환합니다. = 1은 숫자가 홀수임을 의미합니다. 또는 00000000 = 0, 숫자가 짝수임을 의미합니다.

예를 들어

홀수입니까?

1 & 1 =

00000001 &

00000001 =

00000001 < - 홀수

2 & 1 =

00000010 &

00000001 =

00000000 < - 심지어

54 & 1 =

00000001 &

00110110 =

00000000 < - 심지어

이것이 이것이 작동하는 이유입니다.

if(number & 1){

   //Number is odd

} else {

   //Number is even
}

이것이 중복되면 죄송합니다.

번호 제로 패리티 | 영 http://tinyurl.com/oexhr3k

파이썬 코드 시퀀스.

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

산출:

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

토론을 위해 ...

주어진 숫자의 마지막 숫자 만 살펴보면 균일한지 또는 홀수인지 확인하면됩니다. 서명, 서명되지 않은, 긍정적, 부정적인 - 그것들과 관련하여 모두 동일합니다. 그래서 이것은 모든 라운드에서 작동해야합니다 : -

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

여기서 핵심은 세 번째 코드 라인에 있으며, 디비전 연산자는 정수 부서를 수행하므로 결과의 분수 부분이 누락되었습니다. 예를 들어 222 / 10은 결과적으로 22를 제공합니다. 그런 다음 다시 10으로 곱하면 220이 있습니다. 원래 222에서 그것을 빼면 2로 끝납니다. 2로 끝납니다. 마법은 원래 숫자의 마지막 숫자와 동일한 숫자입니다. ;-) 괄호는 계산이 수행 된 순서를 상기시키기 위해 있습니다. 먼저 분할과 곱셈을 한 다음 원래 번호에서 결과를 빼십시오. 뺄셈보다 분할과 곱셈의 우선 순위가 높기 때문에 우리는 그것들을 떠날 수 있지만, 이것은 우리에게 "더 읽기 쉬운"코드를 제공합니다.

우리가 원한다면 모든 것을 완전히 읽을 수 없게 만들 수 있습니다. 현대 컴파일러에는 아무런 차이가 없습니다.

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

그러나 코드는 미래에 유지하기가 더 어려워 질 것입니다. 홀수 숫자에 대한 텍스트를 "도"로 변경하고 싶다고 상상해보십시오. 그런 다음 다른 사람이 나중에 어떤 변화가 무엇인지 확인하고 SVN Diff 또는 이와 유사하게 수행하고 싶습니다 ...

휴대성에 대해 걱정하지 않고 속도에 대해 더 걱정이된다면 최소한의 비트를 살펴볼 수 있습니다. 해당 비트가 1으로 설정되면 홀수 인 경우 0이면 짝수 숫자입니다. Intel의 X86 아키텍처와 같은 작은 엔디 언 시스템에서는 다음과 같습니다.

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

효율적으로 원한다면 BitWise 연산자를 사용하십시오 (x & 1), 그러나 읽을 수 있으려면 Modulo 2 (x % 2)

짝수 또는 이상한 점검은 간단한 작업입니다.

우리는 정확히 2로 나눌 수있는 숫자는 짝수 숫자라는 것을 알고 있습니다.

우리는 단지 숫자의 분할 가능성을 확인하고 사용하는 분할 가능성을 확인하기 만하면됩니다. % 운영자

다른 경우에도 이상한 점검

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

c 다른 경우 C 프로그램을 사용하거나 홀수를 확인하는 프로그램

조건부/삼여 작업자 사용

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

C 조건부 운영자를 사용하여 균일하거나 홀수를 확인하는 C 프로그램.

비트 타이어 연산자 사용

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

+66% 더 빨리> !(i%2) / i%2 == 0

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

코드는 정수의 마지막 비트를 확인합니다. 1 이진에서

설명

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

알아채다 가장 오른쪽 조금 항상 1입니다 이상한 번호.

그만큼 & 비트와 운영자는 우리의 가장 오른쪽 비트를 확인합니다 반품 1 인 경우 라인

그것을 참 & 거짓으로 생각하십시오

우리가 비교할 때 N ~와 함께 1 이는 의미합니다 0001 바이너리에서 (0의 수는 중요하지 않습니다).
그럼 우리가 정수가 있다고 상상해 봅시다. N 크기가 1 바이트입니다.

8 비트 / 8 이진 숫자로 표시됩니다.

int N ~였다 7 그리고 우리는 그것을 비교합니다 1, 같아요

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

어느 에프 거짓과 사실.

그것 비교 둘 다 사실이라면 가장 옳은 비트입니다. 자동으로 7 & 1 ~이다 후회.

가장 먼저 비트를 확인하고 싶다면 어떻게해야합니까?

단순히 변경됩니다 n & 1 에게 n & 2 2가 나타납니다 0010 이진 등으로.

초보자 인 경우 16 진수 표기법을 사용하는 것이 좋습니다.
return n & 1; >> return n & 0x01;.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top