如何高效地判断奇数和偶数

在我们日常的编程当中,常常会遇到判断某个整数属于奇数还是偶数的情况。

大家一般的处理做法是用这个整数和2取模。然后判断是等于1还是等于0。

这里,我要为大家介绍一种快速有效的判断做法,利用2进制进行判断。

大家都知道,奇数的最低位一定是1,而偶数的最低位一定是0.所以我们可以根据这个特性,让需要判定的整数和1进行“与”运算,这样就只留下了原数的最低位,然后直接判断这个数等于1还是等于0即可。

实现代码如下:

 1class Program
 2    {
 3        static void Main(string[] args)
 4        {
 5
 6            bool s = OddEven.IsEven(4);
 7
 8            Console.WriteLine(s);
 9
10            s = OddEven.IsOdd(55877554);
11
12            Console.WriteLine(s);
13        }

14    }

15
16    /// <summary>
17    /// 判断一个整数是奇数还是偶数。
18    /// </summary>

19    class OddEven
20    {
21        static private int s = 1;
22
23        static public bool IsEven(int a)
24        {
25            if ((a & s) == 0)
26            {
27                return true;
28            }

29            else
30            {
31                return false;
32            }

33           
34        }

35
36        static public bool IsOdd(int a)
37        {
38            return !IsEven(a);
39        }

40    }


 

posted @ 2007-11-21 14:22 逖靖寒 阅读(2463) 评论(45)  编辑 收藏 所属分类: 读书算法

  回复  引用    
#1楼 2007-11-21 14:33 | fawfa [未注册用户]
不错。
  回复  引用  查看    
#2楼 2007-11-21 14:36 | Jeffrey Zhao      
这样啊……只能说也是一种方式,呵呵。
  回复  引用  查看    
#3楼 2007-11-21 14:36 | ZeroCool      
首先,我也比较相信位运算的效率比取模更高,但楼主既然提出了这种方式比模运算更高效的观点,为什么不提供性能测试数据来支持你的观点呢?这就不够严谨了。

另外,
if ((a & s) == 0)
{
return true;
}
else
{
return false;
}
为什么不可以写成
return ((a & s) ==0);
呢?这样虽然从性能的角度来看变化不大,但至少可以让程序看上去更简洁精炼,毕竟这种简洁并不会损失可读性呀。
  回复  引用  查看    
#4楼 2007-11-21 14:38 | 1-2-3      
不错,不愧是练过C++的。不知工作找得怎么样了?
  回复  引用  查看    
#5楼 2007-11-21 14:40 | Clark Zheng      
学习了,一句话
return ((a & s) ==0);
  回复  引用  查看    
#6楼 [楼主]2007-11-21 14:42 | 逖靖寒      
@ZeroCool

确实,return ((a & s) ==0); 更好。

非常同意您的观点,谢谢。
  回复  引用  查看    
#7楼 [楼主]2007-11-21 14:49 | 逖靖寒      
@1-2-3
找不到工作。
  回复  引用    
#8楼 2007-11-21 14:53 | STS [未注册用户]
too basic.
  回复  引用  查看    
#9楼 2007-11-21 14:54 | GSpring      
有点意思
  回复  引用  查看    
#10楼 2007-11-21 14:55 | 木野狐(Neil Chen)      
用扩展方法更好,不需要 OddEven 这个类。

using System;

namespace IsEven
{
    
class Program
    {
        
static void Main(string[] args)
        {
            Console.WriteLine(
3.IsEven());
            Console.ReadLine();
        }
    }

    
public static class IntExtensions
    {
        
public static bool IsEven(this int i)
        {
            
return (i & 1== 0;
        }
    }
}

  回复  引用  查看    
#11楼 2007-11-21 15:02 | Enzo      
@木野狐(Neil Chen)
不错更简洁,用了新特性,
不过也得他的vs支持哦

  回复  引用  查看    
#12楼 [楼主]2007-11-21 15:04 | 逖靖寒      
@木野狐(Neil Chen)
请问这个是.net3.0里面新加的机制吗?以前没有接触过。
  回复  引用  查看    
#13楼 2007-11-21 15:09 | 木野狐(Neil Chen)      
http://blog.joycode.com/scottgu/archive/2007/10/10/109268.aspx
  回复  引用  查看    
#14楼 2007-11-21 15:11 | 徐少侠      
@逖靖寒
不是,是很久很久以前。C的时代就有的技术
  回复  引用  查看    
#15楼 2007-11-21 15:41 | 大口仔      
不就是位与吗呵呵
  回复  引用  查看    
#16楼 2007-11-21 15:48 | Robert Lee      
return ((a & s) == 0);
受益了:D
  回复  引用  查看    
#17楼 2007-11-21 15:58 | Silent Void      
即使写成%2,编译器在编译时也会做优化的...
  回复  引用  查看    
#18楼 2007-11-21 16:22 | Cat Chen      
将对2的n次访求模自动转换为按位与,这是编译器优化任务之一。
  回复  引用    
#19楼 2007-11-21 16:46 | Kurax Kuang [未注册用户]
这帖子真冷

如果都写成了return ((a & s) ==0);了

那么写成return ((a & 1) ==0);有能怎样

再说,有必要为了判断奇数偶数而去构建一个类么?

我一直认为高级编程中,内存才是最宝贵资源
  回复  引用    
#20楼 2007-11-21 16:58 | A1 [未注册用户]
呵呵,传统技巧。
以位运算代替乘除法的场合还有很多,比如计算2倍,4倍,1/4,1/8什么的。
用异或省去临时变量替换两个变量的方法堪称位此类应用中的经典
但用的时候要注意有符号数和无符号数的区别、数值类型位长、溢出安全问题等等。
  回复  引用    
#21楼 2007-11-21 17:00 | A1 [未注册用户]
@Cat Chen
:-) 我也这么认为。但不知道编译器是否真这么做了。
  回复  引用    
#22楼 2007-11-21 19:40 | 孤帆' [未注册用户]
个人感觉这种苛求是没有什么必要的,请问你这么写代码是否容易理解了呢?
即使是模2算法与位以德算法在实际的使用中(只要不是频繁的调用)也不会见到任何的性能损失的.
  回复  引用  查看    
#23楼 2007-11-21 21:17 | 大石头      
我还有一个办法就是 使用右移,然后判断zf

究竟是位与运算快还是右移运算快?
  回复  引用    
#24楼 2007-11-21 22:50 | 化石 [未注册用户]
右移更快些。
  回复  引用  查看    
#25楼 2007-11-21 23:01 | 無尽海      
确实这种写法没见过得学习学习
public static class IntExtensions
{
public static bool IsEven(this int i)
{
return (i & 1) == 0;
}
}

  回复  引用  查看    
#26楼 2007-11-22 08:55 | 3echo      
不错,学习一下,脑壳好像又灵活一些了!
  回复  引用  查看    
#27楼 2007-11-22 09:12 | 双鱼座      
哈哈,个人同意Kurax Kuang,不同意Cat Chen,依赖编译器从而放弃良好的编码习惯,这是现代程序员的通病。N年前的笑话:
http://www.delphibbs.com/keylife/iblog_show.asp?xid=387
  回复  引用  查看    
#28楼 2007-11-22 09:30 | OOP      
这个效率方面的说法还要经过实际的测试啊。
个人感觉取模操作效率也不会差。
  回复  引用  查看    
#29楼 2007-11-22 09:32 | Clark Zheng      
@双鱼座
果然高手!
  回复  引用  查看    
#30楼 2007-11-22 09:48 | 装配脑袋      
调用一下Static Method,代价可能都是任何奇偶判断方法的百倍
  回复  引用  查看    
#31楼 2007-11-22 10:11 | wenanry      
只学习了一条话:return (i & 1) == 0;
同时问一句:
public static bool IsEven(this int i)

static public bool IsEven(this int i)
有什么区别?
  回复  引用  查看    
#32楼 [楼主]2007-11-22 11:59 | 逖靖寒      
@wenanry
没有区别!
  回复  引用  查看    
#33楼 2007-11-22 12:20 | Zhuang miao      
只是一种方法~至于效率问题.....??说不好
  回复  引用  查看    
#34楼 [楼主]2007-11-22 13:46 | 逖靖寒      
可以用以下代码进行效率的测试:
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication44
{
class Program
{
static void Main(string[] args)
{
int a = -25547788;
int len = 500000000;

DateTime start1 = DateTime.Now;

for (int i = 0; i < len; i++)
{
OddEven.IsEven(a);
}

TimeSpan ts1 = DateTime.Now - start1;

Console.WriteLine("使用位操作的时间:" + ts1.TotalMilliseconds);

DateTime start2 = DateTime.Now;

for (int i = 0; i < len; i++)
{
Mod2.IsEven(a);
}

TimeSpan ts2 = DateTime.Now - start2;

Console.WriteLine("使用求模操作的时间:" + ts2.TotalMilliseconds);
}
}

/// <summary>
/// 判断一个整数是奇数还是偶数。使用位操作
/// </summary>
static class OddEven
{
static public bool IsEven(int a)
{
return ((a & 1) == 0);
}

static public bool IsOdd(int a)
{
return !IsEven(a);
}
}

/// <summary>
/// 判断一个整数是奇数还是偶数。使用求模操作
/// </summary>
static class Mod2
{
static public bool IsEven(int a)
{
return ((a % 2) == 0);
}

static public bool IsOdd(int a)
{
return !IsEven(a);
}
}
}

  回复  引用    
#35楼 2007-11-22 14:05 | 560889223 [未注册用户]
实测差距不大,相较位运算法,与2求模法存在一个2%~4%的额外损耗。测试使用随机数生成器生成一亿个正整数进行测试。

DateTime startTime = DateTime.Now;
for (int i = 0; i < size; i++)
{
if ((r.Next() & 1) == 0)
oddCount++;
else
evenCount++;
}
DateTime endTime = DateTime.Now;
  回复  引用  查看    
#36楼 [楼主]2007-11-22 14:10 | 逖靖寒      
@560889223
>与2求模法存在一个2%~4%的额外损耗
这是怎么获得的数据啊?
  回复  引用  查看    
#37楼 2007-11-22 14:11 | 周银辉      
为什么IsOdd还要去调用一次IsEven呢,函数体本来就很简洁的,多一次函数调用很高效么
  回复  引用  查看    
#38楼 2007-11-22 21:28 | Dream world 梦想天空      
还是用简洁、易懂的方式比较好,毕竟现在电脑CPU速度已经很过剩了~~剩下的就是对人大脑的考验了:)
  回复  引用  查看    
#39楼 2007-11-22 22:23 | 地狱门神      
什么是良好的编码习惯?这是一个问题。
  回复  引用  查看    
#40楼 2007-11-23 16:12 | 天行健([@])      
不错,不愧是练过C++的。
  回复  引用  查看    
#41楼 2008-03-04 09:05 | floodpeak      
呵呵,一眼就看出来你是个学生
跟我当年一个样
为了点儿小性能废了半天劲,最后人家还不知情
这种研究很有益,但如果是实际开发要在程序性能和开发进度间仔细权衡
  回复  引用  查看    
#42楼 [楼主]2008-03-04 09:39 | 逖靖寒      
@floodpeak
是,谢谢指教。
  回复  引用  查看    
#43楼 2008-03-04 13:53 | 双鱼座      
@floodpeak
我看你连个学生也不如。你做事完全只是为了让别人知情么?
象你这样的态度,进度也高不到哪里去。虽然快快交差了,但是毛病一堆。算上你调试、优化的时间,比人家还多出一截来。
讲究细节的目的不仅仅是为了手头的某个程序,而是为了养成一些良好的习惯,有了这些习惯,提升系统质量无需任何成本。
  回复  引用  查看    
#44楼 2008-03-04 14:10 | floodpeak      
@双鱼座
……

  回复  引用    
#45楼 2008-07-15 11:51 | 随便看看 [未注册用户]
不错 受教了