一道简单的面试题,发现自己的bug
题目
int a = 4;
System.out.println(~a);
int b = -4;
System.out.println(~b);
问:程序输出什么
答案:-5和3
解释
前提:
一个字节有8位,首位为符号位,1为负数,0为正数。如10000001 = -1(十进制),00000001 = 1(十进制)
- 正数补码 = 原码
- 负数补码在计算的时候按照以下两条规则:
负数补码 = 【原码符号位】+【剩余原码从右往左除第一个1外,左边按位取反】
或
负数补码 = 【原码符号位】 + 【剩余原码按位取反后+1】
举个例子
10000001 的补码 = 111111111
10000101的补码 = 11111011
针对题目解释
在java中存储的二进制一般为数字补码。因此java在运算的时候是按照补码来计算的。针对运算符~ ,在java运算中就是根据补码取反。
因此我们计算中按照以下顺序来计算
- 将数据的原码转为补码
- 补码按位取反,此时取反后还是补码,我们需要在计算中转为原码
- 将取反后的补码转补码
针对4:
- 4的二进制为00000100
- 在java中保存 的补码是00000100
- 根据运算符~ 按位取反是 11111011
- 然后显示的时候我们将补码转为原码,在进行一次负数补码运算得到
10000101 = -5
针对-4:
- -4的二进制是 10000100
- 在Java中保存的补码是11111100
- 根据运算符~ 按位取反是 00000011
- 然后将补码转为原码,因为补码的符号位为0,因此补码与原码一致为00000011 = 3