分享到:

位操作

1、与

将某一位置为0,可以使用与。将该位与'0'进行与操作,其他位与'1'进行与操作。

例如:

  bits:0111 1010,我希望把第3位和第1位都置于0,则把(0111 1010)和(1111 0101)进行与操作。

  (0111 1010 )& (1111 0101) = 0111 0000

2、或

将某一位直为1,可以使用或。将该位与'1'进行或操作,将其他位与'0'进行或操作。

例如:

  bits:0111 1010,我希望把第2位和第0位都置于1,则把(0111 1010)和(0000 0101)进行或操作。

  (0111 1010)|(0000 0101)= 0111 1111

3、异或

4、状态位

  利用二进制来表示多种状态集合,灵活的组合多种状态。

示例1:

  某支付系统中,订单的状态主要有两种类别,即是否已经支付,是否已经结算。我们用一个整型字段status来表示订单的状态,其中status的二进制位中第0位表示支付状态,第1位表示结算状态。如果已经支付,则status的二进制表示形式为*1;否则为*0。如果已经结算,则status的二进制表示形式为1*;否则为0*。其中*表示另外一个状态位的值。

  然后我们定义状态常量(status_i),PAY = 0x01;SETTLE = 0x02;其中PAY的二进制表示为01,SETTLE的二进制表示为10。

  通过status和状态常量(status_i)的与操作,即可判断订单状态。status & status_i其结果不为零,表示第i个状态为真

  status & PAY = 0,则表示第0位为'0',即未支付;否则第0位为'1',即已支付。

  status & SETTLE = 0,则表示第1位为'1',即已结算;否则第1位为'1',即已结算。

  当业务逻辑发生变化,需要添加一种状态类别的时候,我们可以继续利用status剩余的二进制位。ADD_STATUS = 0x04。

#include <iostream>

int main()
{
    using namespace std;
    int status;
    const int PAY = 0x01;
    const int SETTLE = 0x02;
    const int OLD = 0x04;
    while(cin >> status)
    {
        if (status & PAY)
        {
            cout << "PAY\t";
        }
        else
        {
            cout << "NOT_PAY\t";
        }

        if (status & SETTLE)
        {
            cout << "SETTLE\t";
        }
        else
        {
            cout << "NOT_SETTLE\t";
        }

        if (status & OLD)
        {
            cout << "OLD\n";
        }
        else
        {
            cout << "NOT_OLD\n";
        }
    }
    return 0;
}

 

示例2:

  在网络通信中,如果客户端需要把信息更新到服务器,我们可以制定一条更新协议,协议包体的数据结构包含了所有需要被更新的字段。

public class ClientInfo {
    
    private int id;
    
    private String name;
    
    private List<Friend> friends;
    
    private List<Order> orders;

    .....
}

  在实际需求中,我们往往频繁的更新部分字段。一种节省通信成本的解决方案是拆分协议,把更新协议拆分为频繁的和非频繁的。另外一种解决方案就是在协议包中添加修改标记状态位。协议包中只包含需要更新的字段,并且把该状态位设置为'1'。

    final int FIELD_NONE = 0;
    final int FIELD_1 = 1;
    final int FIELD_2 = 2;
    final int FIELD_3 = 4;
    final int FIELD_4 = 8;
    final int FIELD_5 = 16;
    ......
    
    int flag = 0;
    // 设置第一个字段
    flag |= FIELD_1;
    
    // 设置第四个字段
    flag |= FIELD_4;
    
    packet.setFlag(flag);    

  在服务器端,只需通过flag与常量状态位进行“与”操作,即可判断是否需要更新该字段。

5、状态位在J2SE中的应用

java.util.regex.Pattern

public final class Pattern implements java.io.Serializable {

        public static final int UNIX_LINES = 0x01;
        public static final int CASE_INSENSITIVE = 0x02;
        public static final int COMMENTS = 0x04;
        public static final int MULTILINE = 0x08;
        public static final int LITERAL = 0x10;
        public static final int DOTALL = 0x20;
        public static final int UNICODE_CASE = 0x40;
        public static final int CANON_EQ = 0x80;

        public static Pattern compile(String regex, int flags) {
                return new Pattern(regex, flags);
        }    

        /**
         * Indicates whether a particular flag is set or not.
         */
        private boolean has(int f) {
            return (flags & f) != 0;
        }

        private void compile() {
            // Handle canonical equivalences
            if (has(CANON_EQ) && !has(LITERAL)) {
                normalize();
            } else {
                normalizedPattern = pattern;
            }
            // ....... MORE OTHER CODE
        }       
} 

 

posted @ 2012-10-16 19:40  onliny  阅读(369)  评论(0编辑  收藏  举报