这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
一篇文章搞懂Byte
一般和单片机打交道使用的是
byte,byte是java中最小的单位了,极限优化,一个byte是8个bit,虽然bit只有0和1表示,但在编程的设计场景中已经可以表示很多东西了,比如错误和正确的状态,比如失败和成功的状态。那么在java中如何处理这些场景呢。
一、计算机的最小单位
讲这个问题之前,为了方便记忆,先讲一个由来。
据说世界上最简单的计算机是一个灯泡。
它可以通电、可以断电,通电就亮了,断电就灭了。
而在现代的计算机上只是让这种通电、断电的场景变得复杂。
通电相当于告诉它1,断电就相当于告诉它0。
通电和断电也可以被称作高电平低电平。
所以计算机中最小的单位的值就是0和1,0和1被称作位,也就是bit
二、Java语言中的最小单位
计算机中的最小单位是位(bit),那么在java中最小的单位是什么呢。
java中的基本数据类型有:
byte(字节) 8位
short(短整数) 16位
int(整数) 32位
long(长整数) 64位
float(单精度) 32位
double(双精度)64位
char(字符) 16位
boolean(布尔值)8位
除了8个基本数据类型之外,还有常用的String行勒,它是个一个比较特殊的存在,下次专门用一篇文章取理解它。
通过上诉,Java中最小的单位是byte
三、理解Byte类型
- 在Java中Byte的特性
-
是最小的数据类型
-
值范围在[-128, 127],是带符号位
signed byte
- 理解
signed和byte概念。
-
signed表示有符号的,也就是有正负数的概念 -
unsigned表示无符号的,只有大小,也就是只有正数的概念
- 什么是符号位?
对于signed带符号的表示来说,第一个bit位代表着正负,如果是0代表正数,如果位1,代表负数。比如十进制的1,对应二进制位0000 0001,第一个0为1,则为正1,也就是1
- 为什么java中的取值范围是[-128, 127] ?
因为java采用带有符号位的表示方法。
三、Byte和bit的转化
既然一个byte 等于8个bit,那么java中又怎么获取byte中的bit呢?
3.1 从byte中取出8个bit
假设声明一个byte = 1,我们取出这个byte的8个位分别是多少。
// 声明
byte a = 1;
// 第一位
byte bit1 = (byte) ((a >> 7) & 1);
byte bit2 = (byte) ((a >> 6) & 1);
byte bit3 = (byte) ((a >> 5) & 1);
byte bit4 = (byte) ((a >> 4) & 1);
byte bit5 = (byte) ((a >> 3) & 1);
byte bit6 = (byte) ((a >> 2) & 1);
byte bit7 = (byte) ((a >> 1) & 1);
byte bit8 = (byte) ((a >> 0) & 1);
Log.d(TAG, "bit1:" + bit1); // 0
Log.d(TAG, "bit2:" + bit2); // 0
Log.d(TAG, "bit3:" + bit3); // 0
Log.d(TAG, "bit4:" + bit4); // 0
Log.d(TAG, "bit5:" + bit5); // 0
Log.d(TAG, "bit6:" + bit6); // 0
Log.d(TAG, "bit7:" + bit7); // 0
Log.d(TAG, "bit8:" + bit8); // 1
来分析下代码。
首先在程序员计算器中得到正确的值,分析它的结构。
对于Mac:计算器->显示->编程器
对于Windows:win+R -> 输入 calc 回车 -> 程序员计算器。
通过计算器可以得知,
十进制的1 对应的二进制的 0000 0001
那我们怎么把这些 0000 0001 分别取出来了。
原始数据 0000 0001
取第一位,就右移动7位,变成 0000 0000
然后&1,也就是&上 0000 0001
& 的含义是相同为1,不同为0
流程如图
0000 0001
>> 7
0000 0000
&
0000 0001
-----------------
0000 0001
结果为 1
3.2 将8个bit合成一个byte
那么如何将八个字节和成一个byte呢?
byte[] array = new byte[8];
array[0] = 0;
array[1] = 1;
array[2] = 1;
array[3] = 1;
array[4] = 0;
array[5] = 0;
array[6] = 1;
array[7] = 1;
byte temp = (byte) (array[0] << 7 | array[1] << 6 | array[2] << 5 | array[3] << 4 | array[4] << 3 | array[5] << 2 | array[6] << 1 | array[7]);
Log.d(TAG, "temp:" + temp); // 115
继续分析下代码。
原八个二进制 移位后
00000000 <<7 00000000
00000001 <<6 01000000
00000001 <<5 00100000
00000001 <<4 00010000
00000000 <<3 00000000
00000000 <<2 00000000
00000001 <<1 00000010
00000001 <<0 00000001
进行或 | 运算,有1为1,否则为0
二进制:01110011 十进制 115
四、Byte与Int的转换
先观察一个现象。
byte a = 127;
int b = (byte) -3;
int c = (byte) 255;
Log.d(TAG, "a & b & c:" + a + "&" + (b) + "&"+(c));
// a & b & c:127&-3&-1
由于讲过java中byte是有符号位的
所以在超过这个范围后就会变成负数
那么如果和无符号位的单片机(c语言)对接的呢。
那么就要用到位运算将无符号的位的数,转化成有符号位的数了。
只需要将这个数 &0xff 即可
byte a = 127;
int b = (byte) -3;
int c = (byte) 255;
Log.d(TAG, "a & b & c:" + a + "&" + (b & 0xff) + "&" + (c & 0xff));
// a & b & c:127&253&255
分析一下代码
0xff 使用0x开头表示,代表着16进制的数
那么16进制的0xff的二进制是多少呢
是 1111 1111
& 之后,保留原来的数据,但是转化成int,前面补上 3x8=24 个零,而第一位的零是符号位。
所以得到的都是正数了。