首页 > 技术文章 > 设备通道开启关闭状态 - 二进制的使用

LcxSummer 2020-05-15 11:28 原文

设备有开和关两个状态,用0表示关、1表示开,不同设备类型通道数不同,目前通道数分8、16、24、32四种,以最简单的8通道来说,11111111 八个 1 表示8个通道全开,这个8位数其实可以看做一个二进制数字,每一位都有0和1两种值,每一位数都可以代表一个通道的状态,这个2进制转化为10进制就是:

2^0 + 2^1 + 2^2 + 2^3 + 2^4 + 2^5 + 2^6 + 2^7

= 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128

= 255

顺便说一个不相关的事,其实 2^0 + 2^1 + 2^2 + 2^3 + 2^4 + 2^5 + 2^6 + 2^7 就等于 2^8 - 1,so easy

那么如果要记录一个设备的8个通道全开,只要记录一个字段(比如ChannelStatus),值记录为 255 即可

00000000 八个 0 ,这个就简单了,这个ChannelStatus字段值记录为 0 即可

那么如果只有4号通道是开启的,其他通道都是关闭的改如何表示呢,很明显,2进制形式应该是 0000 1000 (为了方便看清楚位置,四位空格隔开),转为10进制就是:

0 + 0 + 0 + 2^3 + 0 + 0 + 0 + 0

= 8

通过上述的讲解,很容易发现,如果通道状态是关闭的,它对ChannelStatus这个字段的值的增量是 0 ,如果是开启的,它对ChannelStatus这个字段的值的增量是 2 的 (通道号 -1) 次方,根据这个规律,ChannelStatus的计算方式如下:

ChannelStatus  = 0;

for (Channel ch : channelList) {

  if (ch 是开启的) {

    int chstu = (int) Math.pow(2, ch的通道号 - 1);

    ChannelStatus += chstu 

  }

}

下面介绍下反向计算:

如果已知ChannelStatus的值,如何知道某个通道是什么状态呢?

有人可能会想,这个简单,把ChannelStatus的值转为2进制,比如12,二进制就是 0000 1100 ,很明显3号、4号通道是开启的,这个思路是对的,只是这个3号、4号是开启的是你的肉眼判断出来的,如何让代码来判断出这个结果呢?

又有人可能会说,转成字符串,拆分成数组,然后for循环判断就好了,行也是行的,这里我要介绍另一种判断方式,这里设计到二进制的与计算,0和0或者1相与都是0,只有1和1相与结果是1

那么 判断通道3是否开启,只需要用 ChannelStatus的值,与 0000 0100相与,0000 0100只有第3位是1,那么其他位无论与0还是1相与都是0,唯独这个第3位,如果与1相与是1,与0相与是0,那么 0000 0100 无论和什么数相与,结果只有两种,0000 0000 或者 0000 0100 ,也就是说只要结果不是0(或者结果和该通道的2进制值相当),就可以判断该通道是开启的,代码表达如下:

ChannelStatus  是一个已知数

for (Channel ch : channelList) {

  int chstu = (int) Math.pow(2, ch的通道号 - 1);

  if ((chstu & ChannelStatus) == chstu) { // 或者判断 (chstu & ChannelStatus) != 0

    ch.set状态为开启

  }

}

完结!

推荐阅读