如何检查整数是偶数还是奇数?

我怎样才能检查一个给定的数字在C中是偶数还是奇数?

使用模(%)运算符来检查除以2时是否有余数:

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

有几个人批评我的回答上面说过使用x&1是“更快”还是“更高效”。 我不相信这是事实。

出于好奇,我创build了两个简单的testing用例程序:

 /* 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),发现在每种情况下,for.c和modulo.c的输出是相同的(它们都使用andl $ 1,%eax指令)。 我怀疑这是一个“新”function,我怀疑它可以追溯到古代版本。 我也怀疑任何现代(在过去20年中制造的)非商业或开源的非神秘编译器,都缺乏这样的优化。 我会testing其他编译器,但我目前没有任何可用的。

如果其他人会考虑testing其他编译器和/或平台目标,并得到不同的结果,我会很感兴趣知道。

最后,标准模式保证整数是正数,负数还是零,而不pipe实现是否有符号整型的表示。 按位和版本不是。 是的,我意识到补码有些无处不在,所以这不是一个真正的问题。

你们是waaaaaaaay太高效了。 你真正想要的是:

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

这比使用分割或模数更快。

[笑话模式=“开”]

 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标准规定负数可以用三种方式表示:

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

请注意,此方法使用涉及两个函数的尾recursion。 如果您的编译器像Scheme编译器一样支持尾recursion,那么它可以被有效地实现(变成一段时间/直到某种循环)。 在这种情况下,堆栈不应该溢出!

一个数字即使除以二,余数为0.如果除以2,余数为1,则数字是奇数。

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

我会build立一个奇偶校验表(如果奇数为0,如果奇数的话)(所以可以做一个查找:D),但是gcc不会让我创build这样的数组:

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

所以,让我们来求取偶数和奇数的math定义。

即使存在整数k使得n = 2k,整数n也是偶数。

如果存在整数k使得n = 2k + 1,则整数n是奇数。

这是它的代码:

 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-整数表示给定C编译中int的可能值。 (请注意,C整数是整数的一个子集。)

现在人们可能会担心,对于C中的给定n,整数k可能不存在于C中。 但是有一点certificate,可以certificate对于所有整数n,| n | <= | 2n | (*),其中| n | 是“n如果n是正数,否则是”n“。 换句话说,对于整数n,至less有下列之一成立(事实上,无论是(1和2)还是案例(3和4),但我不会在这里certificate):

情况1:n <= 2n。

情况2:-n <= – 2n。

情况3:-n <= 2n。

情况4:n <= – 2n。

现在取2k = n。 (如果n是偶数,这样的确存在,但我不会在这里certificate它,如果n不是偶数,那么循环even不能提前返回,所以没关系)但是这意味着k <n if对于所有的m,z,整数2m = z意味着z不等于m,因为m不是0。在n是0的情况下,2 * 0 = 0所以0即使我们完成(如果n = 0,那么0是C整数,因为n在函数even是C整数,因此k = 0是C整数)。 因此,如果n是偶数,则C整数中的这种ak存在于C整数中。

类似的论点表明,如果n是奇数,那么在C整数中存在ak,使得n = 2k + 1。

因此,这里呈现的odd函数对于所有的C整数都能正常工作。

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

这是跟@RocketRoy关于他的答案的讨论的后续,但是对于任何想要比较这些结果的人来说都是有用的。

tl; dr根据我所看到的,Roy的方法( (0xFFFFFFFF == (x | 0xFFFFFFFE) )并没有完全针对x & 1作为mod方法进行优化,但是在实践中,运行时间在所有情况下应该相等。

所以,首先我使用Compiler Explorer比较编译的输出:

testingfunction:

 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和-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与-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 

一直到CLANG,它意识到三个案件在function上是平等的。 但是,Roy的方法在GCC中并没有得到优化,所以YMMV。

它与Visual Studio类似; 检查这三个函数的拆卸版本x64(VS2015),我可以看到比较部分对于“mod”和“and”情况是相等的,对于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)之后,运行一个实际的基准testing,结果是完全相等的(同样,Visual Studio 2005 x86 / x64,Release build,不附带任何debugging器)。

发布程序集使用test指令来处理and mod情况,而Roy的情况使用了cmp eax,0FFFFFFFFh方法,但是它被大量的展开和优化,所以在实践中没有区别。

20次运行后我的结果(i7 3610QM,Windows 10功耗计划设置为高性能):

 [testing:Plain mod 2]平均时间:689.29毫秒(相对差异:+ 0.000%)
 [testing:按位或]平均时间:689.63 ms(相对差异:+ 0.048%)
 [testing:按位和]平均时间:687.80毫秒(相对差异:-0.217%)

这些选项之间的差异小于0.3%,所以在所有情况下,组件是相当明显的。

这里是代码,如果有人想尝试,与一个警告,我只testing它在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; } 

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

正如有些人所发布的,有很多方法可以做到这一点。 根据这个网站 ,最快的方法是模数运算符:

 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 

有多less人甚至知道Math.System.DivRem方法或为什么会使用它?

试试这个: return (((a>>1)<<1) == a)

例:

 a = 10101011 ----------------- a>>1 --> 01010101 a<<1 --> 10101010 b = 10011100 ----------------- b>>1 --> 01001110 b<<1 --> 10011100 

读这个相当有趣的讨论,我记得我有一个真实世界,时间敏感的function,testing主循环内的奇数和偶数。 这是一个整数幂函数,贴在StackOverflow其他地方,如下所示。 基准是相当惊人的。 至less在这个现实世界的function中, 模数比较慢 ,而且显着。 获胜者大部分需要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%的方法

对于那些认为理论,或汇编语言列表的人来说,解决这样的争论,这应该是一个警示的故事。 天地间有更多的东西,霍雷肖,比你的哲学梦想的还要多。

我知道这只是语法糖, 只适用于.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 } } 

按位方法取决于整数的内部表示。 Modulo可以在有模运算符的地方工作。 例如,有些系统实际上使用低级别标记(如dynamic语言),所以在这种情况下,原始的x&1实际上不起作用。

IsOdd(int x){return true; }

正确性的certificate – 考虑所有正整数的集合,并假设有一组非整数的非奇数。 因为正整数是有序的,所以会有一个最小而不是奇数,这个数字本身就很奇怪,很明显这个数字不能在这个集合中。 所以这个集合不能是非空的。 重复负整数,除非查找最大的不是奇数。

便携性:

 i % 2 ? odd : even; 

不可移植:

 i & 1 ? odd : even; i << (BITS_PER_INT - 1) ? odd : even; 
 int isOdd(int i){ return(i % 2); } 

完成。

对于我们这些在我们的学习中没有做过多的布尔代数的人来说,更详细地介绍一下按位算子的方法,下面是一个解释。 可能对OP没有多大用处,但我想明确说明为什么NUMBER&1有效。

请注意,就像上面有人回答,负数表示方式可以阻止这种方法的工作。 事实上,它甚至可以打破模运算符方法,因为每种语言在处理负运算数的方式上可能会有所不同。

但是,如果你知道NUMBER总是正面的,那么这个效果很好。

正如上面的“上一句”所指出的那样,只有二进制(和二元)的最后一位数字是重要的。

布尔逻辑“与”门指示两个input必须是1(或高电压),1才能被返回。

1&0 = 0。

0&1 = 0。

0&0 = 0。

1&1 = 1。

如果您将任何数字表示为二进制数(在此我使用了一个8位表示),则奇数在末尾为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 < – Even

54&1 =

00000001&

00110110 =

00000000 < – Even

这就是为什么这个工程:

 if(number & 1){ //Number is odd } else { //Number is even } 

对不起,如果这是多余的。

编号零奇偶| 零http://tinyurl.com/oexhr3k

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

输出:

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

For the sake of discussion…

You only need to look at the last digit in any given number to see if it is even or odd. Signed, unsigned, positive, negative – they are all the same with regards to this. So this should work all round: –

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

The key here is in the third line of code, the division operator performs an integer division, so that result are missing the fraction part of the result. So for example 222 / 10 will give 22 as a result. Then multiply it again with 10 and you have 220. Subtract that from the original 222 and you end up with 2, which by magic is the same number as the last digit in the original number. 😉 The parenthesis are there to remind us of the order the calculation is done in. First do the division and the multiplication, then subtract the result from the original number. We could leave them out, since the priority is higher for division and multiplication than of subtraction, but this gives us "more readable" code.

We could make it all completely unreadable if we wanted to. It would make no difference whatsoever for a modern compiler: –

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

But it would make the code way harder to maintain in the future. Just imagine that you would like to change the text for odd numbers to "is not even". Then someone else later on want to find out what changes you made and perform a svn diff or similar…

If you are not worried about portability but more about speed, you could have a look at the least significant bit. If that bit is set to 1 it is an odd number, if it is 0 it's an even number. On a little endian system, like Intel's x86 architecture it would be something like this: –

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

If you want to be efficient, use bitwise operators ( x & 1 ), but if you want to be readable use modulo 2 ( x % 2 )

Checking even or odd is a simple task.

We know that any number exactly divisible by 2 is even number else odd.

We just need to check divisibility of any number and for checking divisibility we use % operator

Checking even odd using if else

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

C program to check even or odd using if else

Using Conditional/Ternary operator

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

C program to check even or odd using conditional operator .

Using Bitwise operator

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

Modulus operator '%' can be used to check whether a number is odd or even.That is when a number is divided by 2 and if the remainder is 0 then its an even number else its an odd number.

 #include <stdio.h> int main() { int n;//using modulus operator scanf("%d",&n);//take input n from STDIN printf("%s",n%2==0?"Even":"Odd");//prints Even/Odd depending on n to STDOUT return 0; } 

But using Bit manipulation is quite faster than the above method,so if you take a number and apply logically AND '&' to it ,if the answer is 1 then its even else its odd.That is basically we have to check the last bit of the number n in binary.If the last bit is 0 then n is even else its odd.

for example : suppose N = 15 , in binary N = 1111 , now we AND it with 1

  1111 0001 &----- 0001 

Since the result is 1 the number N=15 is Odd.

Again,suppose N = 8 , in binary N = 1000 , now we AND it with 1

  1000 0001 &----- 0000 

Since the result is 0 the number N=8 is Even.

 #include <stdio.h> int main() { int n;//using AND operator scanf("%d",&n);//take input n from STDIN printf("%s",n&1?"Odd":"Even");//prints Even/Odd depending on n to STDOUT return 0; }