java二进制处理_Java中处理二进制移位

我相信,这篇文章读起来会相当有趣。

文章中编程语言是Java,用Java的原因:

第一,Java不做数据溢出校验,这样我们可以忽略溢出异常;

第二,Java普及率比较高,就像是python或shell,几乎人人都会呐。

确定一些位运算符:

|   按位或   1001 | 1010 = 1011  (口诀,有真则真 似or逻辑)

^  按位异或  1001 ^ 1010 = 0011  (口诀,不等则真)

&  按位与   1001 & 1010 = 1000  (口诀,同真则真 似and逻辑)

~  按位取反  ~1001 = 0110 (这条没口诀)

>> 右移 或 位移除法

<

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

1 public static String integerToBinaryString(intinput) {2 char[] charr = new char[32];3 int k = 1;4 booleanisTrue;5 for (int i = 32 - 1; i >= 0; i--) {6 isTrue = (k & input) ==k;7 charr[i] = isTrue ? '1' : '0';8 k = k << 1;9 }10 return newString(charr);11 }

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

调用以下方法:

1 int a = 9;//1001

2 int b = 10;//1010

3 System.out.println(integerToBinaryString(a |b));4 System.out.println(integerToBinaryString(a ^b));5 System.out.println(integerToBinaryString(a & b));

输出结果:

9f22956cd1023a03939ad192e13fe66d.png

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

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

1 int a = 0x12345678;2 Scanner scanner = newScanner(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("'、'

控制台操作:

7f8362007d5481d9531ba563fb938c49.png

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

02b31847d7d737c4f232dcf16a987876.png

通过<>操作,最高位会被0覆盖。

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

bbb6cc5cefaf66ff265937499d0fc494.png

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

b261b48e4b07b85e75bc0bcd6ab24b7f.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

398d4272db5e03797dbbaffa8905eda0.png

作为反码好理解点,就是按位翻转;

补码这东西总是让人云里雾里,有点琢磨不透,其实在二进制运算中,补码就是源码的模。

二进制中定义:正数补码是它本身,负数补码就是它的模了。

有了这层意义,不妨定义一个运算的最大值为13

a=7,b=-2

a+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
    评论
二进制图文详解 二进制Binary 2进制 逢二进一的计数规则。 在计算机内部,一切数据都是2进制的!! 2进制的数字 补码 补码本质是一种解决负数问题的算法。 1. 将数据的一半当做负数使用。 2. 补码在内存是2进制的,显示的时候为10进制。 - Java利用算法支持了补码计算: - Integer.parseInt() - Integer.toString() 3. 补码的缺点: - 不支持超范围计算 - 超范围计算自动溢出 4. 解决补码的缺点:采用更大范围(更多位数)的补码 Java是如何计算 -2-1 的 补码的规律 1. 最大值的规律:最高位0 剩下全是1 - int类型:一个0,31个1 - long类型:一个0,63个1 2. 最小值的规律:最高位1 剩下全是0 - int类型:一个1,31个0 - long类型:一个1,63个0 3. 负数的最高位是1, 正数最高位是0 - 最高位做为识别正数和负数的标志位:称为符号位 - 注意:符号位不是用来表示正负号的!!! 4. -1 的规律:所有位都是1!! 5. 溢出是有规律的! 是一个周期性计算结果。 - 最大值+1 = 最小值 6. 补码的对称现象:-n = ~n + 1 案例: int max = Integer.MAX_VALUE; System.out.println(Integer.toBinaryString(max)); int min = Integer.MIN_VALUE; System.out.println(Integer.toBinaryString(min)); long lmax = Long.MAX_VALUE; System.out.println(Long.toBinaryString(lmax)); long lmin = Long.MIN_VALUE; System.out.println(Long.toBinaryString(lmin)); //-1的规律 int n = -1; System.out.println(Integer.toBinaryString(n)); long l = -1L; System.out.println(Long.toBinaryString(l)); //最大值+1溢出得到最小值 // 推论:Java的int数字是按照补码圆环排列的 int m = Integer.MAX_VALUE+1; System.out.println(m);//最小值 //一个数的溢出测试: n = 345; m = n + Integer.MAX_VALUE+1; System.out.println(m);//负数 m = n + Integer.MAX_VALUE+1+ Integer.MAX_VALUE; System.out.println(m);//344 正数 m = n - (Integer.MAX_VALUE+1+ Integer.MAX_VALUE+1); System.out.println(m);//345 正数 经典面试题1 正数的溢出结果是负数(错误!!!) 经典面试题2 int i = Integer.MAX_VALUE+1; System.out.println( Integer.toBinaryString(i)); 选择运行结果(D): A. 11111111111111111111111111111111 B. 1111111111111111111111111111111 C. 01111111111111111111111111111111 D. 10000000000000000000000000000000 经典面试题3 System.out.println(~-55); 如上代码的运算结果: ( 54 ) System.out.println(~-230); 如上代码的运算结果: ( 229 ) System.out.println(~55); 如上代码的运算结果: ( -56 ) 16进制 16进制是2进制的简写形式 2进制运算 1. ~ 取反运算 2. & 与运算(逻辑乘法) 运算规则: 1 & 1 = 1 1 & 0 = 0 0 & 1 = 0 0 & 0 = 0 与运算用途: n: 00010100 11010111 01010001 11101010 m: 00000000 00000000 00000000 11111111

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值