位运算符 & | ~ ^
& : 对两个二进制数按位做与运算,即 1 & 0 = 0; 1 & 1 = 1; 0 & 0 = 0; | : 对两个二进制数按位做或运算,即 1 & 0 = 1; 1 & 1 = 1; 0 & 0 = 0; ~ : 对一个二进制数按位取反,即 ~1 = 0; ~0 = 1; ^ : 对两个二进制数按位做异或运算,即 1 ^ 1 = 0; 1 ^ 0 = 1, 0 ^ 0 = 0; 相同取0,不同取1
另:
1) 十进制-1 的二进制表示,为书写简单假设 这里的10进制数字是16位的int类型,以下十进制用D()表示 D(1) = 0000 0000 0000 0001 D(-1) 原码 = 1000 0000 0000 0001 D(-1) 补码 = 1111 1111 1111 1111 原码的基础上除符号位以外按位取反后+1 2) 用R表示任意数 2.1) 0 & R = 0; 1 & R = R; R & R = R; 2.2) 1 | R = 1; 0 | R = R; R | R = R; 2.3) 1 ^ R = ~R; 0 ^ R = R; R ^ R = 0;
实例
商城在对商品做分析的时候,需要根据用户行为对商品打一些标记,有许多标记就是‘是/否’的一种逻辑,
假设需要打标记:1 是否促销 2 正品 3 参加双十一 4 参加双十二 等等
提供一个比较好玩的方法
既然这些标记都是‘是否’的取值逻辑,即是否打这个标记,那么我们就可以用二进制来表示。
设定一个int字段,这个字段值的特定位表示特定的tag,取值1表示打标记,取值0表示不打标记
package Binary; public class BinaryTag { static class Goods { private String name; private int tag; public Goods() {} public Goods(String name, int tag) { this.name = name; this.tag = tag; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getTag() { return tag; } public void setTag(int tag) { this.tag = tag; } } class Tag { public final static int None = 0; // 没有标记 public final static int All = -1; // 全部标记 1111 …… 1111 public final static int Promotion = 1; // 促销标记 0001 public final static int Genuine = 2; // 正品标记 0010 public final static int Double11 = 4; // 双十一 0100 public final static int Double12 = 8; // 双十二 1000 } /** * @param args */ public static void main(String[] args) { Goods nike = new Goods("Nike", Tag.None); System.out.print("标为正品;"); mark(nike, Tag.Genuine); System.out.print("参加促销;"); mark(nike, Tag.Promotion); System.out.print("参加双十一;"); mark(nike, Tag.Double11); System.out.println("不参加双十二;"); clearMark(nike, Tag.Double12); descGoods(nike); System.out.println("不促销了,也不参加双十一了;"); clearMark(nike, Tag.Promotion + Tag.Double11); descGoods(nike); System.out.println("反转双十一和双十二的标记;"); reverseMark(nike, Tag.Double11 + Tag.Double12); descGoods(nike); System.out.println("反转双十一和双十二的标记;"); reverseMark(nike, Tag.Double11 + Tag.Double12); descGoods(nike); System.out.println("添加全部标记;"); markAll(nike); descGoods(nike); System.out.println("清除所有标记;"); clearAllMark(nike); descGoods(nike); } /** * 添加某种标记 * @param goods * @param tag */ public static void mark(Goods goods, int tag) { int oldTag = goods.getTag(); // 将tag位 置为1 引用 [2.2) 1 | R = 1; 0 | R = R; R | R = R;] int newTag = (oldTag | tag); goods.setTag(newTag); } /** * 打上所有的标记 * @param goods */ public static void markAll(Goods goods) { goods.setTag(Tag.All); } /** * 消除商品tag * @param goods * @param tag */ public static void clearMark(Goods goods, int tag) { int oldTag = goods.getTag(); int newTag = (oldTag & (~tag)); goods.setTag(newTag); } /** * 消除全部标记 * @param goods */ public static void clearAllMark(Goods goods) { goods.setTag(Tag.None); } /** * 对指定标记进行反转 * @param goods * @param tag */ public static void reverseMark(Goods goods,int tag) { int oldTag = goods.getTag(); int newTag = (oldTag ^ tag); goods.setTag(newTag); } /** * 是否打了这种标记 * @param goods * @param tag * @return */ public static boolean isTaged(Goods goods, int tag) { int oldTag = goods.getTag(); return tag == (oldTag & tag); } public static void descGoods(Goods goods) { System.out.print(goods.getName()+":"); System.out.print((isTaged(goods, Tag.Promotion)?"":"不") + "参加促销;"); System.out.print((isTaged(goods, Tag.Genuine)?"":"不") + "是正品;"); System.out.print((isTaged(goods, Tag.Double11)?"":"不") + "参加双十一;"); System.out.print((isTaged(goods, Tag.Double12)?"":"不") + "参加双十二;"); System.out.println("\n"); } }
Console:
标为正品;参加促销;参加双十一;不参加双十二;
Nike:参加促销;是正品;参加双十一;不参加双十二;
不促销了,也不参加双十一了;
Nike:不参加促销;是正品;不参加双十一;不参加双十二;
反转双十一和双十二的标记;
Nike:不参加促销;是正品;参加双十一;参加双十二;
反转双十一和双十二的标记;
Nike:不参加促销;是正品;不参加双十一;不参加双十二;
添加全部标记;
Nike:参加促销;是正品;参加双十一;参加双十二;
清除所有标记;
Nike:不参加促销;不是正品;不参加双十一;不参加双十二;