C/C++/JAVA 二进制/十六进制 的应用 :大数(超过32位二进制数),按位逻辑运算,属性值设置,等

1 篇文章 0 订阅
1 篇文章 0 订阅

按位逻辑运算,属性设置

按位逻辑运算在高效率的数据操作中应用很多,平时用的高级语言里面,多数时候不需要我们去手动设置这些,因为已经被封装在各种模块/类里面了。

在需要手动定义一些功能的时候,这些运算方法很值得使用。
有一点要注意就是,所有按位运算都是二进制位的按位运算,如果数据采用十进制或者十六进制表示,实际上也是采用二进制的按位运算。

按位与: &

 0&0=0; 1&0=0; 0&1=0; 1&1=1;

(1不变,0变为0)
例如 : 1001&0011 = 0001
负数在计算机中是按照补码的形式存储的,所以要按照补码来按位运算
应用:
1,把指定位清零 。只需要和指定位为0,其他位为1的数进行&运算,这些位就为被置0
2,获取指定位。构造一个二进制数,需要获取的位为1,其他位为0,按位&运算,其结果就是数据的指定位。

按位或: |

0|0=0;   0|1=1;   1|0=1;    1|1=1;

(0不变,1变为1)
应用:
1,把数据的指定位设置为1。例如,如果要把第四位设置为1,那么需要构造一个二进制数:1000,将其与数据进行|预算,那么数据的第四位就会设置为1(不论之前是否是1)

按位异或:^

0^0=0;   0^1=1;   1^0=1;   1^1=0;

(0不变,1反转)
应用:
1,与1异或,可以翻转
2,与0异或,可以保留原值。
这两点很明确。

按位取反:~

~1=0;   ~0=1;

一个按位逻辑运算的应用:属性设置(这个应该有一个学名,暂时还不知道怎么说)

要对一个项目设置一些属性。如果是唯一性的属性倒还好办,比如说,一个项目,可能的属性为a,b,c,只能是其中一种,那么只需要设置这些属性值为一个静态常量,然后去判断一下就好了。

但是很多时候需要设置的属性是多种叠加的。比如说,可能属性是,a,b,c,d,e,f,g。
可以是其中一种,或者几种,可以是ac,也可以是dfg,也可以是e。并且这些属性并没有明确的分类,大多数都是同一类属性的叠加,所以不能分到不同的属性值里面去。
具体来讲,一个窗口,可以是 前台/最大化/透明/窗口化/默认位置/保持最上层 等等这些属性的一个或者几个的叠加。一个文件可以是 文件/文件夹/系统文件/隐藏文件/用户文件 等等这些的一个或者几个的叠加。

这个时候,像唯一属性那样判断就不好用了。最好的办法就是用按位逻辑运算

假设一个项目的属性有8种。那么就构造一个8位二进制数(也就是2位十六进制数)。每一位对应一个属性,设置成静态常量。
a: 0000 0001
b: 0000 0010
c: 0000 0100
d: 0000 1000
…………
如此一来,就可以用按位逻辑运算来构造属性值了。
比如说,我的属性值是abc,那么构造出的值就是:a|b|c.
根据之前的描述,| 运算将会使得对应1的位置是1,也就是说,a|b|c = 0000 0111,这也是一个唯一值,跟所有8种可能属性都不重复。类似的,我们也可以构造出其他的叠加属性,0100 1101,1001 0000 等等

判断属性的时候,需要用到 & 运算。
例如,判断一个项目是否有 a属性,可以:if((attr&a)==a)
根据上面的描述,& 的功能是 :0变为0,1不变。也就是说, attr的值,对应a里面的为0的位,不管是否是0,都会编程0;对应a里面为1的位,则保持不变。
所以,如果attr有a这个属性,那么它的对应a属性的位就会是1,就保持为1;如果没有a这个属性,对应为就是0,运算后依然是0。
而其他位,不管是否是0,都会变成0.因此,可以用if((attr&a)==a)来判断属性。

同理,设置属性的时候用到 | 运算。
假设attr要设置成abcd,只需要简单的这样: attr = a|b|c|d;就可以了

大数(超过32位二进制数)

C语言早已支持64位,有单独的方法操作64位数(目前为止还没有试验过),但是多数时候我们还是在32位里面运算。

在没有支持64位数的时期,要存储一个大数据,比如文件大小,需要用到高低位的存储方法。就是说,在属性里面会对应两个值,一个是低32位,一个是高32位。

在数据量比较小的时候,高位始终为0。如果数据量在低位溢出,就会在高位中 +1。
需要注意一点就是,如果直接写出来的话,只有二进制/十六进制可以直接表示为 【高位-低位】,例如一个数是低位0x1820 ff11, 高位是0x1,那表示出来就是 0x1 1820 ff11
如果是十进制,就需要转换一下,因为高位的 0x1 表示成十进制的时候是 32位最大值+1

如果要做加法,需要高位/低位分开相加,如果低位产生了进位,那就在高位的结果里面加1.
怎么判断低位的进位呢?
如果是无符号数,就简单了,因为进位以后的32位值对应的就只有这32位的值,第33位会被计算机直接忽略,所以,如果 结果小于任意一个相加值,就表示产生了进位。
numA + numB = result;
if(result<numA)…………
有符号数的情况还没有研究过。刚才这个方法也是在网上找到的,还没细看是否有bug。

高低位的表示方法转换成10进制

result = HIGH*(MAXDWORD + 1) + LOW
result – 真实结果
MAXDWORD – 32位数最大值 (0xFFFF FFFF)

那么,怎么表示在计算机里面呢?
0xFFFF FFFF 十进制 就是 4 294 967 295,0x1 0000 0000 实际数值是 4 294 967 296,但是计算机里面直接把超过32位的数值舍去,所以计算机里面这个数就是0x0000 0000,也就是十进制数0

要在计算机上表示超过32位的数值,可以使用以下办法。(自己想的办法,不知道是不是实用)

保存一个指定位数(例如,20位十进制数)的字符数组char bit[20];
将这个数组的每一个位上的字符,对应十进制数的每一个位的数字,然后按照普通的算法进行加减乘除操作。
加法就是 对位相加,如果进位,就在上一位加1。
乘法类似。
除法还没有仔细想过,以后再说吧。

所以,超过32位的数值可以用这种按位表示法来保存,输出的时候也不会存在溢出的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值