如何检查一个整数是偶数还是奇数?
在C语言中如何检查给定的数字是偶数还是奇数?
How can I check if a given number is even or odd in C?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
在C语言中如何检查给定的数字是偶数还是奇数?
How can I check if a given number is even or odd in C?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(30)
使用模 (%) 运算符检查除以 2 时是否有余数:
有些人批评我上面的回答,指出使用 x & 1是“更快”或“更高效”。 我不相信情况是这样。
出于好奇,我创建了两个简单的测试用例程序:
然后我在一台机器上使用 gcc 4.1.3 编译了这些程序 5 次:
我检查了每次编译的汇编输出(使用 gcc -S),发现在每种情况下,and.c 和 modulo.c 的输出是相同的(它们都使用了andl $1, %eax 指令)。 我怀疑这是一个“新”功能,并且我怀疑它可以追溯到古代版本。 我也怀疑任何现代的(过去 20 年制造的)非神秘编译器,无论是商业的还是开源的,都缺乏这样的优化。 我会在其他编译器上进行测试,但目前没有可用的编译器。
如果其他人愿意测试其他编译器和/或平台目标,并得到不同的结果,我很想知道。
最后,标准保证模版本无论整数是正、负还是零都可以工作,无论有符号整数的实现表示如何。 按位与版本不是。 是的,我意识到二进制补码有点普遍存在,所以这并不是一个真正的问题。
Use the modulo (%) operator to check if there's a remainder when dividing by 2:
A few people have criticized my answer above stating that using x & 1 is "faster" or "more efficient". I do not believe this to be the case.
Out of curiosity, I created two trivial test case programs:
I then compiled these with gcc 4.1.3 on one of my machines 5 different times:
I examined the assembly output of each compile (using gcc -S) and found that in each case, the output for and.c and modulo.c were identical (they both used the andl $1, %eax instruction). I doubt this is a "new" feature, and I suspect it dates back to ancient versions. I also doubt any modern (made in the past 20 years) non-arcane compiler, commercial or open source, lacks such optimization. I would test on other compilers, but I don't have any available at the moment.
If anyone else would care to test other compilers and/or platform targets, and gets a different result, I'd be very interested to know.
Finally, the modulo version is guaranteed by the standard to work whether the integer is positive, negative or zero, regardless of the implementation's representation of signed integers. The bitwise-and version is not. Yes, I realise two's complement is somewhat ubiquitous, so this is not really an issue.
你们效率太高了啊啊啊啊啊 您真正想要的是:
重复
isEven
。当然,这不适用于负数。 但辉煌的同时也伴随着牺牲……
You guys are waaaaaaaay too efficient. What you really want is:
Repeat for
isEven
.Of course, that doesn't work for negative numbers. But with brilliance comes sacrifice...
使用位算术:
这比使用除法或模数更快。
Use bit arithmetic:
This is faster than using division or modulus.
[笑话模式=“开”]
[笑话模式=“关”]
编辑:向枚举添加了令人困惑的值。
[Joke mode="on"]
[Joke mode="off"]
EDIT: Added confusing values to the enum.
回应 ffpf - 几年前我和一位同事有过完全相同的争论,答案是不,它不适用于负数。
C 标准规定负数可以用 3 种方式表示:
像这样检查:
适用于 2 的补码以及符号和大小表示,但不适用于 1 的补码。
但是,我相信以下内容适用于所有情况:
感谢 ffpf 指出文本框正在吃掉我的小于字符之后的所有内容!
In response to ffpf - I had exactly the same argument with a colleague years ago, and the answer is no, it doesn't work with negative numbers.
The C standard stipulates that negative numbers can be represented in 3 ways:
Checking like this:
will work for 2's complement and sign and magnitude representation, but not for 1's complement.
However, I believe that the following will work for all cases:
Thanks to ffpf for pointing out that the text box was eating everything after my less than character!
一个不错的方法是:
请注意,此方法使用涉及两个函数的尾递归。 如果您的编译器像Scheme编译器一样支持尾递归,那么它可以有效地实现(变成一种while/until循环)。 在这种情况下堆栈不应该溢出!
A nice one is:
Note that this method use tail recursion involving two functions. It can be implemented efficiently (turned into a while/until kind of loop) if your compiler supports tail recursion like a Scheme compiler. In this case the stack should not overflow !
如果除以 2 余数为 0,则数为偶数。如果除以 2 余数为 1,则数为奇数。
方法很棒!
A number is even if, when divided by two, the remainder is 0. A number is odd if, when divided by 2, the remainder is 1.
Methods are great!
我的意思是除以2,如果余数为0,则为偶数,否则为奇数。
使用模数 (%) 可以让这变得简单。
例如。
4 % 2 = 0 因此 4 是偶数
5 % 2 = 1 因此 5 是奇数
I'd say just divide it by 2 and if there is a 0 remainder, it's even, otherwise it's odd.
Using the modulus (%) makes this easy.
eg.
4 % 2 = 0 therefore 4 is even
5 % 2 = 1 therefore 5 is odd
问题的另一种解决方案
(欢迎孩子们投票)
One more solution to the problem
(children are welcome to vote)
我会建立一个整数的奇偶校验表(如果是奇数则为 0,如果是奇数则为 1)(这样就可以进行查找:D),但是 gcc 不会让我制作这样大小的数组:
所以让我们转而求助于数学偶数和奇数的定义相反。
如果存在使得 n = 2k 的整数 k,则整数 n 是偶数。
如果存在一个整数 k 使得 n = 2k + 1,则整数 n 是奇数。
其代码如下:
让 C 整数表示给定 C 编译中
int
的可能值。 (请注意,C 整数是整数的子集。)现在人们可能会担心,对于 C 整数中给定的 n,对应的整数 k 可能不存在于 C 整数中。 但通过一点证明,可以证明对于所有整数 n,|n| <= |2n| (*),其中 |n| 是“如果 n 为正则为 n,否则为 -n”。 换句话说,对于所有整数 n 至少满足以下条件之一(实际上恰好是情况(1 和 2)或情况(3 和 4),但我不会在这里证明):
情况 1:n < = 2n。
情况2:-n≤-2n。
情况3:-n≤2n。
情况4:n≤-2n。
现在取 2k = n。 (如果 n 是偶数,这样的 ak 确实存在,但我不会在这里证明。如果 n 不是偶数,那么
even
中的循环无论如何都无法提前返回,所以没关系。)但这意味着 k < n 如果通过 (*) n 不为 0,并且对于所有 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 整数中的 n 存在这样的 ak。类似的论证表明,如果 n 是奇数,则 C 整数中存在 ak 使得 n = 2k + 1。
因此,这里介绍的函数
even
和odd
将正常工作对于所有 C 整数。I would build a table of the parities (0 if even 1 if odd) of the integers (so one could do a lookup :D), but gcc won't let me make arrays of such sizes:
So let's instead resort to the mathematical definition of even and odd instead.
An integer n is even if there exists an integer k such that n = 2k.
An integer n is odd if there exists an integer k such that n = 2k + 1.
Here's the code for it:
Let C-integers denote the possible values of
int
in a given C compilation. (Note that C-integers is a subset of the integers.)Now one might worry that for a given n in C-integers that the corresponding integer k might not exist within C-integers. But with a little proof it is can be shown that for all integers n, |n| <= |2n| (*), where |n| is "n if n is positive and -n otherwise". In other words, for all n in integers at least one of the following holds (exactly either cases (1 and 2) or cases (3 and 4) in fact but I won't prove it here):
Case 1: n <= 2n.
Case 2: -n <= -2n.
Case 3: -n <= 2n.
Case 4: n <= -2n.
Now take 2k = n. (Such a k does exist if n is even, but I won't prove it here. If n is not even then the loop in
even
fails to return early anyway, so it doesn't matter.) But this implies k < n if n not 0 by (*) and the fact (again not proven here) that for all m, z in integers 2m = z implies z not equal to m given m is not 0. In the case n is 0, 2*0 = 0 so 0 is even we are done (if n = 0 then 0 is in C-integers because n is in C-integer in the functioneven
, hence k = 0 is in C-integers). Thus such a k in C-integers exists for n in C-integers if n is even.A similar argument shows that if n is odd, there exists a k in C-integers such that n = 2k + 1.
Hence the functions
even
andodd
presented here will work properly for all C-integers.这是一个答案
爪哇:
Here is an answer in
Java:
试试这个:
return (((a>>1)<<1) == a)
示例:
Try this:
return (((a>>1)<<1) == a)
Example:
阅读这个相当有趣的讨论,我记得我有一个现实世界中的时间敏感函数,可以测试主循环内的奇数和偶数。 它是一个整数幂函数,发布在 StackOverflow 上的其他地方,如下所示。 基准测试非常令人惊讶。 至少在这个现实世界的函数中,取模速度较慢,而且明显如此。 获胜者以很大的优势,需要 67% 的模时间,是一种或 ( | ) 方法,并且在本页的其他地方找不到。
对于 3 亿次循环,基准计时如下。
3.962 | 3.962 和掩模方法
4.851 & 方法
5.850 % 方法
对于那些认为理论或汇编语言列表可以解决此类争论的人来说,这应该是一个警示故事。 霍雷肖,天上地下的事物比你的哲学中所梦想的还要多。
Reading this rather entertaining discussion, I remembered that I had a real-world, time-sensitive function that tested for odd and even numbers inside the main loop. It's an integer power function, posted elsewhere on StackOverflow, as follows. The benchmarks were quite surprising. At least in this real-world function, modulo is slower, and significantly so. The winner, by a wide margin, requiring 67% of modulo's time, is an or ( | ) approach, and is nowhere to be found elsewhere on this page.
For 300 million loops, the benchmark timings are as follows.
3.962 the | and mask approach
4.851 the & approach
5.850 the % approach
For people who think theory, or an assembly language listing, settles arguments like these, this should be a cautionary tale. There are more things in heaven and earth, Horatio, than are dreamt of in your philosophy.
这是与 @RocketRoy 关于他的答案讨论的后续内容,但对于任何想要比较的人来说可能会有用这些结果。
tl;dr 据我所知,Roy 的方法 (
(0xFFFFFFFF == (x | 0xFFFFFFFE)
) 并未完全针对x & 1< 进行优化/code> 作为
mod
方法,但实际上在所有情况下运行时间应该相同,因此,首先我使用 编译器资源管理器:
测试的功能:
CLang 3.9.0 with -O3:
GCC 6.2 with - O3:
向 CLang 致敬,它意识到所有三种情况在功能上都是相同的,但是 Roy 的方法并未在 GCC 中进行优化,因此
它与 Visual Studio 的反汇编版本(VS2015)类似 。这三个函数,我可以看到“mod”和“and”情况下的比较部分相等,而 Roy 的“or”情况下的比较部分稍大:
但是,在运行实际基准测试来比较这三个选项(plain mod、按位或、按位与),结果完全相等(同样,Visual Studio 2005 x86/x64,发布版本,未附加调试器)。
对于
and
和mod
情况,发布程序集使用test
指令,而 Roy 的情况则使用cmp eax,0FFFFFFFFh
方法,但它经过大量展开和优化,因此在实践中没有区别。我运行 20 次后的结果(i7 3610QM,Windows 10 电源计划设置为高性能):
这些选项之间的差异小于 0.3%,因此很明显组件在所有情况下都是相同的。
如果有人想尝试的话,这里是代码,但需要注意的是,我只在 Windows 上测试了它(检查
get_time
定义的#if LINUX
条件,并在需要时实现它,取自此答案)。This is a follow up to the discussion with @RocketRoy regarding his answer, but it might be useful to anyone who wants to compare these results.
tl;dr From what I've seen, Roy's approach (
(0xFFFFFFFF == (x | 0xFFFFFFFE)
) is not completely optimized tox & 1
as themod
approach, but in practice running times should turn out equal in all cases.So, first I compared the compiled output using Compiler Explorer:
Functions tested:
CLang 3.9.0 with -O3:
GCC 6.2 with -O3:
Hats down to CLang, it realized that all three cases are functionally equal. However, Roy's approach isn't optimized in GCC, so YMMV.
It's similar with Visual Studio; inspecting the disassembly Release x64 (VS2015) for these three functions, I could see that the comparison part is equal for "mod" and "and" cases, and slightly larger for the Roy's "or" case:
However, after running an actual benchmark for comparing these three options (plain mod, bitwise or, bitwise and), results were completely equal (again, Visual Studio 2005 x86/x64, Release build, no debugger attached).
Release assembly uses the
test
instruction forand
andmod
cases, while Roy's case uses thecmp eax,0FFFFFFFFh
approach, but it's heavily unrolled and optimized so there is no difference in practice.My results after 20 runs (i7 3610QM, Windows 10 power plan set to High Performance):
The difference between these options is less than 0.3%, so it's rather obvious the assembly is equal in all cases.
Here is the code if anyone wants to try, with a caveat that I only tested it on Windows (check the
#if LINUX
conditional for theget_time
definition and implement it if needed, taken from this answer).我知道这只是语法糖,仅适用于 .net 但扩展方法呢...
现在您可以执行以下操作
I know this is just syntactic sugar and only applicable in .net but what about extension method...
Now you can do the following
在“创意但令人困惑的类别”中,我提供:
此主题的一个特定于 Microsoft C++ 的变体:
In the "creative but confusing category" I offer:
A variant on this theme that is specific to Microsoft C++:
按位方法取决于整数的内部表示。 模可以在任何有模运算符的地方工作。 例如,某些系统实际上使用低级位进行标记(如动态语言),因此原始 x & 1 在这种情况下实际上不起作用。
The bitwise method depends on the inner representation of the integer. Modulo will work anywhere there is a modulo operator. For example, some systems actually use the low level bits for tagging (like dynamic languages), so the raw x & 1 won't actually work in that case.
IsOdd(int x) { 返回 true; 正确性证明
- 考虑所有正整数的集合,并假设有一组非奇数的非空整数。 因为正整数是良序的,所以会有一个最小的非奇数,它本身就很奇数,所以很明显这个数字不能在集合中。 因此这个集合不能是非空的。 对负整数重复此操作,但查找最大的非奇数。
IsOdd(int x) { return true; }
Proof of correctness - consider the set of all positive integers and suppose there is a non-empty set of integers that are not odd. Because positive integers are well-ordered, there will be a smallest not odd number, which in itself is pretty odd, so clearly that number can't be in the set. Therefore this set cannot be non-empty. Repeat for negative integers except look for the greatest not odd number.
便携式:
不可便携式:
Portable:
Unportable:
正如一些人所发布的,有很多方法可以做到这一点。 根据这个网站,最快的方法是模运算符:
但是,这里有一些作者标记的其他代码,其运行速度比上面的常见模数运算慢:
有多少人知道 Math.System.DivRem 方法或他们为什么要使用它?
As some people have posted, there are numerous ways to do this. According to this website, the fastest way is the modulus operator:
However, here is some other code that was bench marked by the author which ran slower than the common modulus operation above:
How many people even knew of the Math.System.DivRem method or why would they use it??
完毕。
done.
为了让我们这些在学习中没有做过太多布尔代数的人对按位运算符方法进行更多的阐述,这里有一个解释。 可能对OP没有多大用处,但我想弄清楚为什么 NUMBER & 1 作品。
请注意,就像上面有人回答的那样,负数的表示方式可能会阻止此方法的工作。 事实上,它甚至也可以破坏模运算符方法,因为每种语言处理负操作数的方式可能有所不同。
但是,如果您知道 NUMBER 始终为正数,那么这种方法就很有效。
正如 Tooony 上面指出的那样,只有二进制(和十进制)中的最后一位数字很重要。
布尔逻辑 AND 门规定两个输入都必须为 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中为&amp;)它与1它将返回00000001,= 1意味着该数字是奇数。 或者 00000000 = 0,表示该数字是偶数。
例如,
奇怪吗?
1 & 1 =
00000001 &
00000001 =
00000001 <— 奇数
2 & 1 =
00000010 &
00000001 =
00000000 <— 偶
54 & 1 =
00000001 &
00110110 =
00000000 <— 即使
这就是它起作用的原因:
抱歉,如果这是多余的。
To give more elaboration on the bitwise operator method for those of us who didn't do much boolean algebra during our studies, here is an explanation. Probably not of much use to the OP, but I felt like making it clear why NUMBER & 1 works.
Please note like as someone answered above, the way negative numbers are represented can stop this method working. In fact it can even break the modulo operator method too since each language can differ in how it deals with negative operands.
However if you know that NUMBER will always be positive, this works well.
As Tooony above made the point that only the last digit in binary (and denary) is important.
A boolean logic AND gate dictates that both inputs have to be a 1 (or high voltage) for 1 to be returned.
1 & 0 = 0.
0 & 1 = 0.
0 & 0 = 0.
1 & 1 = 1.
If you represent any number as binary (I have used an 8 bit representation here), odd numbers have 1 at the end, even numbers have 0.
For example:
1 = 00000001
2 = 00000010
3 = 00000011
4 = 00000100
If you take any number and use bitwise AND (& in java) it by 1 it will either return 00000001, = 1 meaning the number is odd. Or 00000000 = 0, meaning the number is even.
E.g
Is odd?
1 & 1 =
00000001 &
00000001 =
00000001 <— Odd
2 & 1 =
00000010 &
00000001 =
00000000 <— Even
54 & 1 =
00000001 &
00110110 =
00000000 <— Even
This is why this works:
Sorry if this is redundant.
为了便于讨论...
您只需查看任何给定数字的最后一位数字即可确定它是偶数还是奇数。
有符号、无符号、正数、负数——在这方面它们都是一样的。
所以这应该是全面的: -
这里的关键是在代码的第三行,除法运算符执行整数除法,因此结果缺少结果的小数部分。 例如,222 / 10 将得到 22。 然后再乘以 10,得到 220。从原来的 222 中减去它,最后得到 2,这神奇地与原始数字的最后一位数字相同。 ;-)
括号的作用是提醒我们计算的顺序。首先进行除法和乘法,然后用原始数字减去结果。 我们可以将它们排除在外,因为除法和乘法的优先级高于减法,但这为我们提供了“更易读”的代码。
如果我们愿意的话,我们可以让它完全不可读。 对于现代编译器来说,这没有任何区别: -
但它会使代码在将来更难维护。 想象一下,您想将奇数的文本更改为“不是偶数”。 然后其他人稍后想要找出您所做的更改并执行 svn diff 或类似的...
如果您不担心可移植性而是更担心速度,您可以看看最不重要的位。 如果该位设置为 1,则为奇数;如果设置为 0,则为偶数。
在小端系统上,比如 Intel 的 x86 架构,它会是这样的: -
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: -
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: -
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: -
如果您想提高效率,请使用按位运算符 (
x & 1
),但如果您想提高可读性,请使用模 2 (x % 2
)If you want to be efficient, use bitwise operators (
x & 1
), but if you want to be readable use modulo 2 (x % 2
)检查偶数或奇数是一项简单的任务。
我们只需要检查任何数字的整除性,为了检查整除性,我们使用
%
运算符使用 if else 检查偶数
C 程序使用 if else 检查偶数或奇数
使用条件/三元运算符
C 程序使用条件运算符检查偶数或奇数。
使用按位运算符
Checking even or odd is a simple task.
We just need to check divisibility of any number and for checking divisibility we use
%
operatorChecking even odd using if else
C program to check even or odd using if else
Using Conditional/Ternary operator
C program to check even or odd using conditional operator.
Using Bitwise operator
+66% 速度加快 >
!(i%2) / i%2 == 0
中是否为 1
该代码检查整数的最后一位在二进制解释
& 按位 AND 运算符检查 return 行中最右边的位是否为 1
将其视为 true & false
当我们将 n 与 1 进行比较时,这意味着二进制的
0001
(零的数量并不重要)。那么我们假设我们有一个大小为 1 字节的整数 n。
它由 8 位/8 二进制数字表示。
如果 int n 是 7,我们将它与 1 进行比较,就像
F 代表 false 和 < strong>T 为真。
如果我想检查最右边之前的位怎么办?
只需更改
n & 1
到n & 2
其中 2 代表二进制的0010
等等。如果您是按位运算的初学者,我建议使用十六进制表示法
返回 n & 1;
>>>返回 n & 0x01;
。+66% faster >
!(i%2) / i%2 == 0
The code checks the last bit of the integer if it's 1 in Binary
Explanation
the & bitwise AND operator checks the rightmost bit in our return line if it's 1
Think of it as true & false
When we compare n with 1 which means
0001
in binary (number of zeros doesn't matter).then let's just Imagine that we have the integer n with a size of 1 byte.
It'd be represented by 8-bit / 8-binary digits.
If the int n was 7 and we compare it with 1, It's like
Which F stands for false and T for true.
What if I want to check the bit before the rightmost?
Simply change
n & 1
ton & 2
which 2 represents0010
in Binary and so on.I suggest using hexadecimal notation if you're a beginner to bitwise operations
return n & 1;
>>return n & 0x01;
.模运算符“%”可用于检查一个数是奇数还是偶数。即当一个数除以 2 时,如果余数为 0,则为偶数,否则为奇数。
但使用 Bit操作比上面的方法要快得多,所以如果你取一个数字并逻辑应用 AND '&' 对此,如果答案是 1,则为偶数,否则为奇数。基本上,我们必须检查二进制数 n 的最后一位。如果最后一位为 0,则 n 为偶数,否则为奇数。
例如:假设 N = 15 ,二进制 N = 1111 ,现在我们将其与 1 进行 AND
由于结果是 1,所以数字 N=15 是奇数。
再次,假设 N = 8 ,以二进制表示 N = 1000 ,现在我们将其与 1 进行与,
因为结果是 0,所以数字 N=8 是偶数。
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.
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
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
Since the result is 0 the number N=8 is Even.