Chr*_*ung 449
使用modulo(%)运算符检查除以2时是否有余数:
if (x % 2) { /* x is odd */ }
Run Code Online (Sandbox Code Playgroud)
有几个人批评我上面的回答说明使用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;
}
Run Code Online (Sandbox Code Playgroud)
然后我用gcc 4.1.3在我的一台机器上编译了5次不同的时间:
我检查了每个编译的汇编输出(使用gcc -S),发现在每种情况下,and.c和modulo.c的输出都是相同的(它们都使用了andl $ 1,%eax指令).我怀疑这是一个"新"功能,我怀疑它可以追溯到古代版本.我也怀疑任何现代(在过去20年制造)非晦涩的编译器,商业或开源,缺乏这样的优化.我会测试其他编译器,但目前我还没有.
如果其他人愿意测试其他编译器和/或平台目标,并得到不同的结果,我会非常有兴趣知道.
最后,无论实现的有符号整数的表示如何,标准都可以保证模数版本能够工作,无论整数是正数,负数还是零.按位和版本不是.是的,我意识到两个补码有点无处不在,所以这不是一个真正的问题.
SCd*_*CdF 208
你们是waaaaaaaay太高效了.你真正想要的是:
public boolean isOdd(int num) {
int i = 0;
boolean odd = false;
while (i != num) {
odd = !odd;
i = i + 1;
}
return odd;
}
Run Code Online (Sandbox Code Playgroud)
重复一遍isEven.
当然,这对负数不起作用.但凭借辉煌而牺牲......
Ada*_*rce 97
使用位算术:
if((x & 1) == 0)
printf("EVEN!\n");
else
printf("ODD!\n");
Run Code Online (Sandbox Code Playgroud)
这比使用除法或模数更快.
Skl*_*vvz 36
[笑话模式="开"]
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;
}
}
Run Code Online (Sandbox Code Playgroud)
[笑话模式="关闭"]
编辑:为枚举添加了令人困惑的值.
And*_*mbe 16
为了回应ffpf - 几年前我与一位同事的论点完全相同,答案是否定的,它不适用于负数.
C标准规定负数可以用3种方式表示:
像这样检查:
isEven = (x & 1);
Run Code Online (Sandbox Code Playgroud)
将用于2的补码和符号和幅度表示,但不适用于1的补码.
但是,我相信以下内容适用于所有情况:
isEven = (x & 1) ^ ((-1 & 1) | ((x < 0) ? 0 : 1)));
Run Code Online (Sandbox Code Playgroud)
感谢ffpf指出文本框在我的不足之后正在吃掉所有内容!
Pie*_*rre 14
一个不错的是:
/*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
}
Run Code Online (Sandbox Code Playgroud)
请注意,此方法使用涉及两个函数的尾递归.如果你的编译器像Scheme编译器一样支持尾递归,它可以有效地实现(变成while/until循环).在这种情况下,堆栈不应该溢出!
jjn*_*guy 11
一个数字即使,当除以2时,余数为0.如果除以2,则余数为1时,数字为奇数.
// Java
public static boolean isOdd(int num){
return num % 2 != 0;
}
/* C */
int isOdd(int num){
return num % 2;
}
Run Code Online (Sandbox Code Playgroud)
方法很棒!
问题的另一个解决方案
(欢迎儿童投票)
bool isEven(unsigned int x)
{
unsigned int half1 = 0, half2 = 0;
while (x)
{
if (x) { half1++; x--; }
if (x) { half2++; x--; }
}
return half1 == half2;
}
Run Code Online (Sandbox Code Playgroud)
我会构建一个奇偶校验表(0甚至1,如果奇数)的整数表(所以可以进行查找:D),但是gcc不会让我创建这样大小的数组:
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];
}
Run Code Online (Sandbox Code Playgroud)
所以让我们改为使用偶数和奇数的数学定义.
即使存在整数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;
}
Run Code Online (Sandbox Code Playgroud)
设C-整数表示int给定C编译中的可能值.(注意,C-integers是整数的子集.)
现在有人可能会担心,对于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是偶数,那么确实存在,但我不会在这里证明.如果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在函数中是C-整数even,因此k = 0是C-整数).因此,如果n是偶数,则C-整数中的n存在于C-整数中的n.
类似的论证表明,如果n是奇数,则在C-整数中存在ak,使得n = 2k + 1.
因此,功能even和odd这里提出将正常工作为所有的C-整数.
// C#
bool isEven = ((i % 2) == 0);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
358502 次 |
| 最近记录: |