C# 关于数据为0或者1时存储在字节中的内存优化

实际应用过程中,接收其他的通讯过来的数据时,有些可能是开关信号,要么为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

这样写只是多一两步的运算,但是如果是长时间的数据采集和存储时,能大大减少数据的存储量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yangzm996

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值