实际应用过程中,接收其他的通讯过来的数据时,有些可能是开关信号,要么为0,要么为1。如果我们也按照普通的字节去存,用一整个字节来存一个开关信号,势必会造成内存的浪费。
大家都知道一个字节有8位,每一位上的值为0或者1。那么我可不可以用一个字节来存取8个开关信号呢?
public byte set_bit(byte data, int index, bool flag)
{
//data 为要写入的字节,index为要设置的第几位(1~8),flag为真实需要设置1,为假需要设置0
if (index > 8 || index < 1)
throw new ArgumentOutOfRangeException();
int v = index < 2 ? index : (2 << (index - 2));
//得出等下要计算的数 index 为 1~8 时,数值分别为 1 2 4 8 16 32 64 128
return flag ? (byte)(data | v) : (byte)(data & ~v);
//要设置为1的话,就用当前的数和 计算的数 或一下就OK了
//要设置为0的话,~v 取V的非值,如 1 本来是 0000 0001 取非后 1111 1110 再用这个数去和原来的数与,这样0那位一定是0
//同理 2 本来是 0000 0010 取非后 1111 1101,再用这个数去和原来的数与,原来的数的第二位一定能置为0
}
public int[] getbit(byte byte1)
{
int[] bit = new int[8];
bit[7] = (byte1 & 128) == 128 ? 1 : 0;
bit[6] = (byte1 & 64) == 64 ? 1 : 0;
bit[5] = (byte1 & 32) == 32 ? 1 : 0;
bit[4] = (byte1 & 16) == 16 ? 1 : 0;
bit[3] = (byte1 & 8) == 8 ? 1 : 0;
bit[2] = (byte1 & 4) == 4 ? 1 : 0;
bit[1] = (byte1 & 2) == 2 ? 1 : 0;
bit[0] = (byte1 & 1) == 1 ? 1 : 0;
return bit;
}
private void Form1_Load(object sender, EventArgs e)
{
byte testdata = 0;
//接下来开始设置 1010 1010 十进制为170
testdata = set_bit(testdata,1,false);
//0000 0000 0
listBox1.Items.Add("设置完第一位为0后值为:"+ testdata);
testdata = set_bit(testdata, 2, true);
//0000 0010 2
listBox1.Items.Add("设置完第二位为1后值为:" + testdata);
testdata = set_bit(testdata, 3, false);
listBox1.Items.Add("设置完第三位为0后值为:" + testdata);
testdata = set_bit(testdata, 4, true);
//0000 1010 10
listBox1.Items.Add("设置完第四位为1后值为:" + testdata);
testdata = set_bit(testdata, 5, false);
listBox1.Items.Add("设置完第五位为0后值为:" + testdata);
testdata = set_bit(testdata, 6, true);
//0010 1010 42
listBox1.Items.Add("设置完第六位为1后值为:" + testdata);
testdata = set_bit(testdata, 7, false);
listBox1.Items.Add("设置完第七位为0后值为:" + testdata);
testdata = set_bit(testdata, 8, true);
//1010 1010 170
listBox1.Items.Add("设置完第八位为1后值为:" + testdata);
int[] result = getbit(testdata);
StringBuilder sb = new StringBuilder();
//按从第一到第八位排列
result.ToList().ForEach(t=>sb.Append(string.Format("{0},",t)));
listBox1.Items.Add(sb.ToString());
}
首先,我们可以在电脑自带的计算机中,快速得到二进制转换为其他进制的值。
其实在设置的过程中,设置第几位的值为1或0时,过程如下
在设置中, int v = index < 2 ? index : (2 << (index - 2));
2 << (index - 2) 的意思是左移多少位的意思。
如2左移一位时,由
变为
2左移三位时,变为
所以得到 index为1到8 时,
v为 1 2 4 8 16 32 64 128
对应的二进制为
0000 0001
0000 0010
0000 0100
0000 1000
0001 0000
0010 0000
0100 0000
1000 0000
要设置某一位为1时,用原值与v去或 即 (byte)(data | v) ,我们的v在设置第几位上的值已经为1了,或之后原值该位上一定为1。
要设置某一位为0时,我们先取v的非,即~v(记得自己写时要记得转换为字节,int类型会出现负数),
取~v后,即v中 1变为0,0变为1。对于v等于1时,值由0000 0001 变为 1111 1110。此时再用原值与v去与,我们在要设置的位数上已经是0了,与之后原值该位上一定为0。
在获取时,我们要获取该字节上的值就更简单了
举例第一位 : bit[1] = (byte1 & 2) == 2 ? 1 : 0;
2对应的二进制为 0000 0010
用原值与2进行与,除了第2位其他位因为2都为0,所以一定为0,
当原值第二位为1时,值为 0000 0010 等于2,返回值为1
当原值第二位为0时,值为 0000 0000 不等于2,返回值为0
这样写只是多一两步的运算,但是如果是长时间的数据采集和存储时,能大大减少数据的存储量。