java 2进制字符串移位,Java中处理二进制移位

第一,Java不做数据溢出校验,这样我们可以忽略溢出异常;第二,Java普及率比较高,就像是python或shell,几乎人人都会呐。

确定一些位运算符:|   按位或   1001 | 1010 = 1011  (口诀,有真则真 似or逻辑)^  按位异或  1001 ^ 1010 = 0011  (口诀,不等则真)&  按位与   1001 & 1010 = 1000  (口诀,同真则真 似and逻辑)~  按位取反  ~1001 = 0110(这条没口诀)>> 右移 或 位移除法<

以下是一个将十进制数转化为二进制数显示为字符串的方法,为了方便我之后的测试而做此转换方法:

copycode.gif1     public static String integerToBinaryString(int input) { 2         char[] charr = new char[32]; 3         int k = 1; 4         boolean isTrue; 5         for (int i = 32 - 1; i >= 0; i--) { 6             isTrue = (k & input) == k; 7             charr[i] = isTrue ? '1' : '0'; 8             k = k <

copycode.gif

此处我没有使用Integer.toBinaryString(n),是因为这个返回会忽略前面的所有零情况,二进制数据长度很难对齐,给分析带来很大难度。所以就自己做了integerToBinaryString方法,注意此方法从最低位开始计算每个位的值,因为我这里用Java写的测试,而Java是不支持无符号(unsigned)类型数据,有符号和无符号数据在 << 时规则是相同的,但是 >> 时,有符号和无符号会因最高位为符号位的限制,产生一些规则不同的问题,之后做个测试说明。

调用以下方法:1         int a = 9;// 10012         int b = 10;// 10103         System.out.println(integerToBinaryString(a | b));4         System.out.println(integerToBinaryString(a ^ b));5         System.out.println(integerToBinaryString(a & b));

输出结果:

660970-20170510180027644-1354275265.png

以上结果用来验证我说的三个口诀,可见口诀正确。

请用以下代码进行测试位移:

copycode.gif1         int a = 0x12345678; 2         Scanner scanner = new Scanner(System.in); 3         while (true) { 4             System.out.println(integerToBinaryString(a)); 5             System.out.println(Integer.toHexString(a) + "\t" + a); 6             System.out.print("输入:"); 7             String in = scanner.next(); 8             if (in.startsWith(">")) { 9                 a >>= 1;10             } else if (in.startsWith("'、'

copycode.gif

控制台操作:

660970-20170510180133441-1161002063.png

由上位移可见,当a的最高位为1时(图片第四步骤),进行>>操作,最高位不会被0取代,继续进行操作:

660970-20170510181527207-1570851326.png

通过<>操作,最高位会被0覆盖。以上简单的测试,只是为了解释一下在有符号位情况下,左移和右移操作的稍许不同之处,当然无符号情况下,最高位为1时,进行>>操作,最高位会被0覆盖。这是为什么呢?还是找一些官方解释比较有说服力。

660970-20170510181539660-258284926.png

这本教材是我大学里的必修课程,177页中位移除法对此有详细说明。

660970-20170510181555176-447887605.png

当然这个说法还是过于粗糙了,当了解了运算器对有符号位运算原理,或许就能豁然开朗了。我还是说一些比较好玩的东西吧。补码和反码1 int b = -20;2 int bb = ~b;3 int bbb = ~b + 1;4 System.out.println(integerToBinaryString(b));5 System.out.println(integerToBinaryString(bb));6 System.out.println(integerToBinaryString(bbb));

补码bbb和反码bb

660970-20170510181712863-1549477340.png

作为反码好理解点,就是按位翻转;补码这东西总是让人云里雾里,有点琢磨不透,其实在二进制运算中,补码就是源码的模。二进制中定义:正数补码是它本身,负数补码就是它的模了。

有了这层意义,不妨定义一个运算的最大值为13a=7,b=-2a+b==? 当然用简单运算的确能求出值为5但是我要以以下方法求值bb == b%13 == 11这里要能理解 bb == b,否则很难解释下去了。那么 a+b == a+bb == 7+11 == 18因此时18大于13,超出部分会溢出,所以a+b == 18%13 == 5跟我想当然理解 a+b == 7 +(-2) == 7-2 == 5 的值完全吻合此时,无符号位移位除法空位设置0就很好理解,因为无符号的数一定都是非负数,其补码就是它本身;有符号位移位除法空位被设置为1估计也就好理解了,是为了方便此负数转补码时空位转为0,当然这只是其中一点原因,也许深刻了解运算器构造和原理,对此问题会有个更好的认识。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值