Java 中的二进制
二进制是 计算机技术中广泛采用的一种数制。二进制数据是用 0 和 1 两个数码来表示的数。
它的基数为 2,进位规则是 “逢二进一”,借位规则是 “借一当二”
1. 正整数的二进制表示法
十进制 | 二进制 | 十进制 | 二进制 | 十进制 | 二进制 | 十进制 | 二进制 |
0 | 0 | 3 | 11 | 6 | 110 | 9 | 1001 |
1 | 1 | 4 | 100 | 7 | 111 | 10 | 1010 |
2 | 10 | 5 | 101 | 8 | 1000 | 11 | 1011 |
1.1 十进制转换成二进制
示例:将 46 转换为二进制
从下往上 46 转换为 二进制: 101110
46 / 2 = 23;// 余 0
23 / 2 = 11;// 余 1
11 / 2 = 5; // 余 1
5 / 2 = 2; // 余 1
2 / 2 = 1; // 余 0
1 / 2 = 0; // 余 1
1.2 二进制转换成十进制
示例: 将 10110 转化为 十进制数
1 0 1 1 1 0
5 4 3 2 1 0 // 每个位上的值代表 2 的 n 次方
32 16 8 4 2 1 // 每个位上的 1 代表的十进制的大小
32+0 +8+ 4+ 2+ 0 = 46
2. 负整数的二进制表示法
内存中一个字节占 8 位,第一位表示符号位,0 表示正数,1 表示负数
符号位( 0 表示正数,1表示负数)数字位数字位数字位数字位数字位数字位数字位00101110
2.1 十进制转换为二进制
示例: 将 -46 转换为二进制数
- 将 46 转换为二进制数 --> 00101110
- 将这个二进制数按位去反 --> 11010001
- 最后对二进制数 +1 --> 11010010
2.2 二进制转换为十进制
将 8 位的二进制数字 11010010 转换成十进制
- 根据符号位判断 正负
- 正数直接按照上面的方法处理
- 负数
- 先 -1 --> 11010001
- 取反 --> 00101110
- 再按照正数的方式转换为十进制 46
- 加上符号得到最终结果: -46
3. 其他进制
十进制 | 二进制 | 八进制 | 十六进制 |
0 | 0 | 0 | 0 |
1 | 1 | 1 | 1 |
2 | 10 | 2 | 2 |
3 | 11 | 3 | 3 |
4 | 100 | 4 | 4 |
5 | 101 | 5 | 5 |
6 | 110 | 6 | 6 |
7 | 111 | 7 | 7 |
8 | 1000 | 10 | 8 |
9 | 1001 | 11 | 9 |
10 | 1010 | 12 | A |
11 | 1011 | 13 | B |
12 | 1100 | 14 | C |
13 | 1101 | 15 | D |
14 | 1110 | 16 | E |
16 | 10000 | 20 | 10 |
17 | 10001 | 21 | 11 |
18 | 10010 | 22 | 12 |
19 | 10011 | 23 | 13 |
20 | 10100 | 24 | 14 |
3.1 二进制转换成八进制
- 将二进制转换为 八进制, 2 的 3 次方等于 8,所以可以将二进制数的每 3 位转换位 8 进制数的 1 位。反之亦然。
- 如下图 01010111 转换为 八进制为 127
3.2 二进制转换成十六进制
- 将二进制转换成为 十六进制,由于 2 的 4 次方等于 16,所以可以将二进制的每 4 位 转换成 16 进制数的 1 位。反之亦然。
- 下图 将 01010111 转换成为 十六进制为 57
4. Java 中的多种进制
4.1 多种进制的表示
- 十进制
int a = 10;
- 二进制
Java 中 0b 或者 0B 开头表示 二进制数
int b = 0b0010;
int c = 0B0010;
- 八进制
Java 中使用 0 开头表示八进制数
int d = 010;
- 十六进制
Java 中使用 0x 或 0X 开头表示 十六进制数
int e = 0x4A;
int f = 0X4A;
4.2 多种进制的转换
- 整数类型十进制数 转换为二进制字符串
String binaryNumber = Integer.toBinaryString(100);
- 整数类型十进制数 转换为八进制字符串
String octalNumber = Integer.toOctalString(100);
- 整数类型十进制数 转换为十六进制字符串
String hexadecimalNumber = Integer.toHexString(100);
- 将字符串按照指定的进制进行解析
- 使用
Integer.valueOf()
方法解析字符串,默认按照 十进制解析,也可以自定义解析方式。- 如果数据不符合解析的进制,会发生
NumberFormatException
。
String val = "31";
Integer.valueOf(val,8);// 按照 8 进制进行解析:25
Integer.valueOf(val,16);// 按照 16 进制进行解析:49
4.3 二进制和 Java 中的数据类型
- byte
- Java 中 byte 占 8 位,8 位的二进制数最大为 01111111 --> 转换为十进制 127(
- 8 位可表示的最小二进制数位 10000000 --> 转换为十进制 -128 (
- byte 的取值范围: -128 ~ 127
Byte.MIN_VALUE Byte.MAX_VALUE
- short
- 在 Java 中 short 占 16 位
- short 的取值范围: ~
Short.MIN_VALUE Short.MAX_VALUE
- int
- 占 32 位
- 取值范围: ~
Integer.MIN_VALUE Integer.MAX_VALUE
- long
- 占 64 位
- 取值范围: ~
Long.MIN_VALUE Long.MAX_VALUE
- char
char 类型占 64 位,但是 char 类型没有 符号位(也称 无符号),取值范围 在 0 ~
4.4 二进制的浮点数
- 现代计算机一般以 IEEE 754 标准存储浮点数
对于 float 类型: 占 32 位,数符分配是 1 位,阶码分配是 8 位,尾数分配是 23 位。
数符 | 阶码 | 尾数 | 总尾数 | 偏移值 | |
短实数 | 1 | 8 | 23 | 32 | 127 |
长实数 | 1 | 11 | 52 | 64 | 1023 |
临时实数 | 1 | 15 | 64 | 80 | 16383 |
- 示例: 178.125 转换为 二进制
- 先把整数部分和小数部分分别转换为 二进制
- 整数部分:10110010
- 小数部分:001
- 合起来:10110010.001
- 转换为二进制浮点数,即把小数点位移到整数位只有 1,即为:
- 把浮点数转换二进制后,对应 3 部分的值
- 数符:正数,所以是 0
- 阶码:阶码的计算公式( 阶码 ( 111 )+偏移量( 01111111 ) )
- 尾数:小数点后面的数( 011001001 )
- 最终展示:
4.5 Java 浮点数
- Java 中浮点数 float 和 int 内存中都占用 32 位,但是 float 的范围要比 int 更大(原因参照上面二进制的浮点数,由于阶码的存在,同样的位数,浮点数可以表示更大的范围),但是也导致 当数值太大以后,尾数位不够大,导致 float 的精度将会下降,所以 虽然 float 类型的范围比 int 大,但是 int 转换为 float 时,可能会出现 精度丢失的情况。
1.23456792E8 (
int n = 123456789;
float f = n;
System.out.println(n);// 123456789
System.out.println(f);// 1.23456792E8
5. 位运算符
5.1 非( ~ )
非运算:按位取反。
( int 为 32 位,前面的 0 省略 )
x11111010500000101
int x = ~5; // -6
5.2 与( & )
与运算:只有当两个操作数都为 1 的时候才取 1,否则就取 0。
( int 为 32 位,前面的 0 省略 )
x00000100600000110500000101
int x = 5 & 6; // 4
5.3 或( | )
或运算:只要有一个操作数为 1 结果就为 1。
( int 为 32 位,前面的 0 省略 )
x00000111500000101600000110
int x = 5 | 6;// 7
5.4 异或( ^ )
异或运算:当两个操作数不同时,结果为 1;两个操作数相同时,结果为 0。
( int 为 32 位,前面的 0 省略 )
x00000011500000101600000110
int x = 5 ^ 6; // 3
5.5 右移( >> )
- 正数右移相当于十进制除法运算除以
( int 为 32 位,前面的 0 省略 )
500000101x00000010y00000001int x = 5 >> 1;// 2 int y = 5 >> 2; // 1
5.6 左移( << )
- 正数左移相当于十进制乘法运算操作数乘以
( int 为 32 位,前面的 0 省略 )
500000101x00001010y00010100int x = 5 << 1; // 10 int y = 5 << 2; // 20
5.7 无符号右移( >>> )
无符号右移:将所有操作数向 右 位移 n 位,前面空出的用 0 补足,对于正数 与 运算相同,对于负数
5.8 问题
- 有 10 瓶药,其中有 若干瓶 坏药,已知 好药每颗重 1 克,坏药每颗重 0.9 克,有一个秤,只能秤一次,找到所有的坏药。
药瓶编号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
取出药数 | ||||||||||
实际重量 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
最大重量 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |