1、正数怎么用二进制表达
现在以四位为例,四位只能表示表示 -8 ~ 7,一共16个数(2^4)。java语言中32位的int类型和64位的long类型可以表示更多数。
以四位为例,正数的第一位一定是0,比如十进制的6在二进制中就是0110。
2、负数怎么用二进制表达
还是以四位为例,负数的第一位一定是1。一个负数(比如-6)转换成一个二进制难以直接写出,但是在这里只需要记住一个原则:一个数取反再加1就是他的相反数,就很好解决了。
将 -6转换成一个二进制,我们可以先写出6的二进制形式,再取反加一,就是-6的二进制形式。6的二进制形式是0110,取反则为1001,再加一则为1010,故1010就是二进制的-6。
如果反过来,我们知道负数的二进制形式,怎么知道它的十进制形式呢?还是一样,取反加一获得他的相反数就可以。比如1010,第一位是1,肯定是个负数,我们要知道具体是哪个负数,先取反得到0101,再加一得到0110,0110在十进制中表示6(这个可以明显看出),故1010就表示 -6。
扩展开来,无论是32位还是64位的表示形式,都可以用一样的原则。
但对于整数最小值,一个数取反再加1就是他的相反数这个原则不适用,比如1000,表示-8,4位表示的最小的数就是-8,将1000取反加一还是1000,是-8本身,并不能得到8,这是因为4位只能表示正数-8~7,8不在这个范围中。
3、常见的位运算(|,&,^,~,<<,>>,>>>)
|:位运算或。0110 | 1001 = 1111,对每一位取或运算,相同位置只要至少有一个1结果就是1,否则为0。
&:位运算与。0111 & 1001 = 0001,对每一位取与运算,相同位置必须全是1结果才是1,否则为0。
^:位运算亦或。0111 ^ 1001 = 1110,对每一位取亦或运算,相同位置相同则为0相异则为1。
~:取反运算。~0111 = 1000, 对每一位取反。
<<:左移运算。这里拿32位举例,对于正数:
x = 00000000000000000000000000001010,
x << 1 = 00000000000000000000000000010100,
整体向左移动一位,右边缺的用0补齐。
对于负数:
y = 10000000000000000000000000001010,
y<<1 = 10000000000000000000000000010100,
整体向左移动一位,右边缺的用0补齐,左边继续是以1开头。
>>和>>>:右移运算。对于非负数,>>和>>>都是一样的效果,比如正数:
x = 00000000000000000000000000001010,
x>>1 = x>>>1 =00000000000000000000000000000101。
对于负数,负数做>>运算,整体向右移动,左边用1补齐,负数做>>>运算,整体向右移动,左边用0补齐。例如
y = 11110000000000000000000000000000,
y >> 2 = 11111100000000000000000000000000,
y>>>2 = 00111100000000000000000000000000。
因此对于非负数,有一个规律:非负数>>i,等同与除以2的i次方。非负数<<i,等同于乘以2的i次方。
4、|、&与||、&&的区别
区别1:|和&是位运算,||和&&是逻辑运算,||和&&两端只能链接boolean类型,比如4||5,1&&2这种写法都是错误的。
区别2:通常来讲,||和&&的效率更高,比如,对于a&&b,a若位假,则不会判断b,直接返回假,但对于a&b,即使判断a为假后,也会判断b,下面用一个例子证明。
public class Bit {
public staic void main(String[] args) {
returnTrue() | returnFalse(); //进入了returnTrue,进入了returnFalse
System.out.println("test1测试结束");
returnFalse() & returnTrue(); //进入了returnFalse,进入了returnFalse
System.out.println("test2测试结束");
returnTrue() || returnFalse(); //进入了returnTrue,没有进入returnFalse
System.out.println("test3测试结束");
returnFalse() && returnTrue(); //进入了returnFalse,没有进入returnTrue
System.out.println("test4测试结束");
}
public staic boolean returnTrue(){
System.out.println("进入了returnTrue函数");
return True;
}
public staic boolean returnFalse(){
System.out.println("进入了returnFalse函数");
return False;
}
}
5、java中一个打印二进制的函数
实现输入一个整型int,可以输出该整型的二进制形式。
public class BinarySystem {
pubilic static void main(String[] args) {
int a = 6;
int b = 0b0110; //这是6的java二进制表示法
printBinary(a); //输出00000000000000000000000000000110
printBinary(b); //输出00000000000000000000000000000110
}
public static void printBinary(int num) {
for(int i = 31; i >= 0; i--) {
System.out.print((num & (1 << i)) == 0 ? "0": "1");
//为什么可以这样写
//以6为例,6的二进制形式为0110,进入第一个循环时,0110 & 1000 = 0,因此打印0;进入第二个循环时,0110 & 0100 = 0100,不等于0,因此打印1,以此类推,最终打印出0110
}
System.out.println();
}
}
6、为什么这样设计二进制,为什么负数的二进制设计如此复杂?
这主要是为了加法逻辑的合理性,接下来解释一下为什么这样设计二进制会使得加法逻辑合理。
以-5+7为例,-5的二进制形式为1011,7的二进制形式为0111,相加得0010,也就是2。注意这里发生了溢出,但计算结果最终还是对的,这就是二进制的精妙之处!