阿拉伯数字采取进位制法,高位在做,低位在右。十进制计数法,基于阿拉伯数字,十进制的数位全都是10^n的形式,这里的10称为十进制计数法的基数,这也就是十进制中“十”的由来。计算机中数据存放以二进制为主。二进制是使用2作为基数,它的位数也就是2^n的形式。
二进制与十进制之间转换
举例,二进制:110101
十进制:1*2^5+1*2^4+0*2^3+1*2^2+0*2^1+1*2^0=53
由此可以推导出八进制、十六进制。
计算机为什么使用二进制?
这和计算机硬件有关,组成计算机系统的逻辑电路通常只有两个状态,即开关的接通和断开。断开用“0”表示,接通用“1”表示。因为只有这两种状态,即便系统在收到干扰是仍然可靠分辨出“0”和“1”,所有,再具体的系统实验中,二进制的数据表达具有抗干扰能力强,可靠性高的优点。
试想,用十进制或者更高的进制位涉及具有10种状态的电路,情况就显得很复杂了,判断状态时出错的几率大大提高了。
不仅在实际硬件电路上,而且在逻辑运算时,“真”“假”也只有2种状态,正好与二进制的“1”“0”对应。逻辑运算中的加法(“或”运算)、乘法(“与”运算)、否定(“非”运算)都可以通过“0”与“1”的加、乘、减来实现。
二进制的位操作
位操作:直接堆内存中的二进制进行操作。常见的二进制位操作包括向左移位和向右移位的移位操作,“或”、“与”、“异或”的逻辑操作。
向左移位
二进制110101向左移1位,就是在末尾添加一位0。
110101 -> 1101010
进行移位操作有可能会发生数字溢出的情况。所谓数字溢出,就是二进制数的位数超过了系统所指定的位数。现在一般主流系统都支持32位整型数字。如果移位操作发生了数字溢出,就需要将溢出的位数去除。
计算一下向左移位前后两个数的十进制数值,之前是53,向左移位后是106。由此可得,二进制左移一位,实际上就是十进制数字翻一倍。
向右移位
二进制110101向右移1位,就是去除末尾的那一位。
110101 -> 11010
计算一下向右移位前后两个数的十进制数值,之前是53,向左移位后是26,这正好是53除以2的整数商。由此可得,右移一位就是将数字除以2求得的整数商的操作。
在Java中代码实现移位操作
import java.math.BigInteger;
public class demo{
public static int leftShift(int num,int m){
return num << m;
}
public static int rightShift(int num,int m){
return num >>> m;
}
}
可见左移右移明显不一样,那为什么右移时不是 “>>”n呢?
这是因为java的二进制数值中最高一位是符号位,当符号位为0,表示该数值的整数,当符号位为1时,表示该数值为负数。
以32位Java为例,我们来看一下53、-53
这里-53用的补码形式
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
补码计算规则:
正整数的原码、反码、补码完全一样,即符号位固定为0,数值位相同。
负整数的符号位固定为1,由原码变为补码时,规则如下:
1、原码符号位1不变,整数的每一位二进制数位求反,得到反码
2、反码符号位1不变,反码数值位最低位加1,得到补码
负整数在进行右移时就会出现是否移动符号位的问题?
这就出现了两种右移。
- 逻辑右移:右移一位,左边补位
- 算术右移:符号位不动,其他右移,空出来的补1
位的“或”
二进制的“1”和“0”对应逻辑中的“真”和“假”,可以针对位进行逻辑操作。逻辑“或”:参与操作的位中只要有一个位是1,那最终结果就是1,即为真。
位的“与”
参与操作的位中必须全都是1,那最终结果为1,即为真。
位的“异或”
参与操作的位相同,那结果就是0,否则就是1.所谓“异或”中的“异”,也就是要参与操作的位不同,才能得到“真”的结果。