精华内容
下载资源
问答
  • 先用与、非操作使除最低位之外的数据置0,再用log2函数取值 int returnPosOfLow1(u_int& occ) { int n = occ; return log2(n & (~n + 1)); }

    先用与、非操作使除最低位之外的数据置0,再用log2函数取值

    int returnPosOfLow1(u_int& occ)
    {
    	int n = occ;
    	return log2(n & (~n + 1));
    }
    
    展开全文
  • 二进制数的运算方法

    万次阅读 多人点赞 2017-08-29 14:12:13
    1.二进制数的算术运算 二进制数的算术运算包括:加、减、乘、除四则运算,下面分别予以介绍。 (1)二进制数的加法 根据“逢二进一”规则,二进制数加法的法则为: 0+0=0 0+1=1+0=1 1+1=0 (进位为1)...

    1.二进制数的算术运算
    二进制数的算术运算包括:加、减、乘、除四则运算,下面分别予以介绍。

    (1)二进制数的加法

      根据“逢二进一”规则,二进制数加法的法则为:
      0+0=0
      0+1=1+0=1
      1+1=0 (进位为1) 
      1+1+1=1 (进位为1)
    
      例如:1110和1011相加过程如下:
    

    在这里插入图片描述

      (2)二进制数的减法
    
      根据“借一有二”的规则,二进制数减法的法则为:
    
      0-0=0
      1-1=0
      1-0=1
      0-1=1 (借位为1)
    
      例如:1101减去1011的过程如下:
    

    在这里插入图片描述

      (3)二进制数的乘法
    
      二进制数乘法过程可仿照十进制数乘法进行。但由于二进制数只有0或1两种可能的乘数位,导致二进制乘法更为简单。二进制数乘法的法则为:
    
      0×0=0
      0×1=1×0=0
      1×1=1
    
      例如:1001和1010相乘的过程如下:
    

    这里写图片描述

      由低位到高位,用乘数的每一位去乘被乘数,若乘数的某一位为1,则该次部分积为被乘数;若乘数的某一位为0,则该次部分积为0。某次部分积的最低位必须和本位乘数对齐,所有部分积相加的结果则为相乘得到的乘积。
    
      (4)二进制数的除法
    
      二进制数除法与十进制数除法很类似。可先从被除数的最高位开始,将被除数(或中间余数)与除数相比较,若被除数(或中间余数)大于除数,则用被除数(或中间余数)减去除数,商为1,并得相减之后的中间余数,否则商为0。再将被除数的下一位移下补充到中间余数的末位,重复以上过程,就可得到所要求的各位商数和最终的余数。
    
      例如:100110÷110的过程如下:
    

    这里写图片描述

      所以,100110÷110=110余10。
    

    2.二进制数的逻辑运算
    二进制数的逻辑运算包括逻辑加法(“或”运算)、逻辑乘法(“与”运算)、逻辑否定(“非”运算)和逻辑“异或”运算。

      (1)逻辑“或”运算
    
      又称为逻辑加,可用符号“+”或“∨”来表示。逻辑“或”运算的规则如下:
    
      0+0=0或0∨0=0
      0+1=1或0∨1=1
      1+0=1或1∨0=1
      1+1=1或1∨1=1
    
      
      可见,两个相“或”的逻辑变量中,只要有一个为1,“或”运算的结果就为1。仅当两个变量都为0时,或运算的结果才为0。计算时,要特别注意和算术运算的加法加以区别。
    
      (2)逻辑“与”运算
    
      又称为逻辑乘,常用符号“×”或“· ”或“∧”表示。“与”运算遵循如下运算规则:
    
      0×1=0或0·1=0或0∧1=0
      1×0=0或1·0=0或1∧0=0
      1×1=1或1·1=1或1∧1=1
    
      可见,两个相“与”的逻辑变量中,只要有一个为0,“与”运算的结果就为0。仅当两个变量都为1时,“与”运算的结果才为1。
    
      (3)逻辑“非”运算
    
      又称为逻辑否定,实际上就是将原逻辑变量的状态求反,其运算规则如下:
    
    
      可见,在变量的上方加一横线表示“非”。逻辑变量为0时,“非”运算的结果为1。逻辑变量为1时,“非”运算的结果为0。
    
      (4)逻辑“异或”运算 
      “异或”运算,常用符号“”或“”来表示,其运算规则为:
    
      00=0 或 00=0
      01=1 或 01=1
      10=1 或 10=1
      11=0 或 11=0
    
      可见:两个相“异或”的逻辑运算变量取值相同时,“异或”的结果为0。取值相异时,“异或”的结果为1
    
    展开全文
  • 要求一个对应二进制最低位为1对应的数字lowbit,如lowbit(5),5的二进制位101,对应的结果就,001即1,lowbit(4),4的二进制位100,对应的结果就,100即4。 由于计算机采用二进制补码作为数学运算,所以可以用x&-x来...

    要求一个数对应二进制最低位为1对应的数字lowbit,如lowbit(5),5的二进制位101,对应的结果就,001即1,lowbit(4),4的二进制位100,对应的结果就,100即4。

    由于计算机采用二进制补码作为数学运算,所以可以用x&-x来求得

    由于负数的补码就是原码取反加1,所以这样按位或可以得到从右侧起第一个

    为1的数。

    举例:

    x=1,原码0001,x的补码就是0001,(以4位表示)

    -x=-1,原码1001,-x的补码就是1111。

    所以x&-x = 1 即是所求结果

    附上python代码

    def lowbit(x):
        return x&-x

    展开全文
  • Redis提供了SETBIT,GETBIT,BITCOUNT,BITOP四个命令用于处理二进制位数组(bit array,又称"位数组"). 位数组的表示 使用SDS结构保存位数组,使用SDS的操作函数处理位数组。但是,为了简化SETBIT的实现,保存位数组的...

    Redis提供了SETBIT,GETBIT,BITCOUNT,BITOP四个命令用于处理二进制位数组(bit array,又称"位数组").

    位数组的表示

    使用SDS结构保存位数组,使用SDS的操作函数处理位数组。但是,为了简化SETBIT的实现,保存位数组的顺序和我们平时书写位数组的顺序是相反的,如设置0000 1010,保存在SDS中是0101 0000。

    位数组:1111 0000 1100 0011 1010 0101 在SDS中保存为 1010 0101 1100 0011 0000 1111

    GETBIT命令的实现

    GETBIT <bitarray> <offset>

    过程如下:

    -1、计算byte = [offset / 8],byte记录了offset偏移量指定的二进制位保存在位数组的哪个字节;
    -2、计算bit = (offset mod 8) + 1,bit记录了offset偏移量指定的二进制位是byte字节的第几个二进制位;
    -3、根据byte和bit的值,在位数组中定位偏移量指定的二进制位,并返回这个位的值。
    复杂度O(1).

     

    SETBIT命令的实现

    SETBIT <bitarray> <offset> <value>

    1、计算len=[offset / 8] + 1,len记录了保存offset偏移量指定的二进制位至少需要多少字节
    2、检查bitarray键保存的位数组长度是否小于len,如果是,扩展SDS长度为len字节,并将所有扩展的长度值置为0
    3、计算byte = [offset / 8],byte记录了offset偏移量指定的位保存在哪个字节;
    4、计算bit = (offset mod 8) + 1,bit记录了offset偏移量指定的二进制位是byte字节的第几个二进制位
    5、根据byte值和bit值,在bitarray键保存的位数组中定位offset指定的二进制位,先记录指定二进制位保存的值到oldvalue,然后将新值设置为这个二进制位的值;
    6、向客户端返回oldvalue。
    复杂度(O)1;

    BITCOUNT命令的实现

    BITCOUNT <bitarray>

    统计给定位数组中,值为1的二进制位的数量。

    二进制位统计算法:


    1、遍历算法:,遍历每个二进制位,在遇到值为1的位时,计数器+1;
    效率太低,每次循环正检查一个二进制位的值是否为1,检查操作执行的次数与位数组包含的二进制位数量成正比。
    2、查表算法:
    对于一个有限集合来说,集合元素的排列方式是有限的;
    对于一个有限长度的位数组来说,它能表示的二进制位排列也是有限的。
    创建一个数字对应位为1个数的表,通过一次读取一个(或多个,需要建更大的映射表)字节,对比数字,就可以知道这个字节有几个位为1。键为数字,值为位上1的个数,查表。
    初看起来,只要我们创建一个足够大的表,那么统计工作就可以轻易地完成,但查表法的实际效果会受到内存和缓存两方面因素的限制:

    • 因为查表法是典型的空间换时间策略,节约的时间越多,花费的内存越大。
    • 查表法的效果会受到CPU缓存的限制:对于固定大小的CPU缓存,创建的表越大,CPU缓存所能保存的内容相比整个表越少,那么查表时出现缓存不命中的情况就会越多,缓存换入和换出操作就会越频繁,最终影响查表法的效率。

    3、variable-precision SWAR算法
    BITCOUNT命令要解决的问题:统计一个位数组中非0二进制位的数量,在数学上被称为“计算韩明重量”。汉明重量经常被用于信息论,编码理论和密码学,所以研究人员开发了多种不同的算法,一些处理器甚至直接带有计算汉明重量的指令,对于不具备这种特殊指令的处理器来说,variable-precision SWAR算法是效率最好的,该算法通过一系列位移和位运算,可以在常数时间内计算多个字节的汉明重量,并且不需要额外的内存。

    以下是一个处理32位长度位数组的算法实现:

    uint32_t swar(uint32_t i){
     //步骤1
     i = (i & 0x55555555) + ((i >> 1) & 0x55555555);
     //步骤2
     i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
     //步骤3
     i = (i & 0x0f0f0f0f) + ((i >> 4) & 0x0f0f0f0f);
     //步骤4
     it = (i * (0x01010101) >> 24);
     return i
    }
    

    执行步骤:

    1、计算出值i的二进制标志可以按每两个二进制位为一组进行分组,各组的十进制表示就是改组的汉明重量;

    2、计算出的值i的二进制表示可以按每四个二进制位为一组进行分组,各组的十进制表示就是改组的汉明重量;

    3、计算出的值i的二进制表示可以按每八个二进制位为一组进行分组,各组的十进制表示就是该组的汉明重量。

    4、i*0x01010101计算出bitarray的汉明重量并记录在二进制位的最高八位,而>>24通过右移运算,将bitarray的汉明重量移动到最低八位,得出的结果就是汉明重量。

    因为swar函数是单纯的计算操作,所以它无需像查表法那样,使用额外的内存。而且swar函数是一个常数复杂度的操作,所以我们可以按照自己的需要,在一次循环中多次执行swar,从而按倍数提升计算汉明重量的效率。

    我们可以按照自己的需要,再一次循环中多次执行swar,从而按倍数提升计算汉明重量的效率:例如,我们在一次循环中调用两次swar函数,那么计算汉明重量的效率就从之前的一次循环计算32位提升到了一次循环计算64位。如果在一次循环中调用四次swar函数,那么一次循环级就可以计算128个二进制的汉明重量,这笔每次循环只调用一次swar函数块4倍。

    当然,一次循环执行多个swar调用这种优化方式是有极限的:一旦循环中处理数组的大小超过了缓存大小,这种优化的效果就会降低并最终消失。

     

    variable-precision SWAR逐行解释:

    第一行

    i = i - ((i >> 1) & 0x55555555);

    0x55555555二进制的标识方式如下:

    0x55555555 = 0b01010101010101010101010101010101

    可以看到的规律是,奇数位为1,偶数位为0。
    表达式((i >> 1) & 0x55555555),将i右移一位,并将所有偶数位设置为0.(等效的,我们也可以通过& 0xAAAAAAAA将所有奇数位设置成0,然后再将结果右移1位)为了方便起见,我们将这个中间值命名为j。
    当我们将中间值j从原始值i中减去会发生什么?那让我们来看看如果i只有两位是什么情况。

        i           j (右移一位)        i - j
    ----------------------------------
    0 = 0b00    0 = 0b00    0 = 0b00
    1 = 0b01    0 = 0b00    1 = 0b01
    2 = 0b10    1 = 0b01    1 = 0b01
    3 = 0b11    1 = 0b01    2 = 0b10

    最后的结论就是i-j的十进制结果就是位数组中1出现的次数。
    那么如果i不只是两位数组呢?实际上,很容易发现i-j的最低两位仍然如上表所示,三四位,五六位也是一个道理,等等。需要注意的是:

    • 由于& 0x55555555的巧妙用法,尽管>> 1,i-j的最低两位不会被i的第三位或者更高的位影响
    • 由于j的最低两位永远不可能在比i的最低两位大。这个减法永远不会向i的第三位借位,因此:对于i-j来说,i的最低两位不会影响i的第三位或者更高位。

    实际上这一行就是将32位数组分为16个两位为单位的组,每组分别计算1出现的次数。
    第二行:

    i = (i & 0x33333333) + ((i >> 2) & 0x33333333);

    与第一行对比,这一行非常的简单。首先,来看一下0x33333333的二进制表示:

    0x33333333 = 0b00110011001100110011001100110011

    i & 0x33333333的目的是以4位为分组取四位中的后两位。而(i >> 2) & 0x33333333在把i右移两位后做同样的工作。然后把它们结果加起来。
    因此,实际上,这行做的工作就是将最低的两位1出现的次数和最低三四位的1出现的次数相加,得到最低四位的1出现的次数。同样的对于输入的8个四位分组(=16进制数)都是一样的。
    第三行:

    return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;

    (i + (i >> 4)) & 0x0F0F0F0F除了这次是用临近的4位1出现的次数系相加,得到8位为一组的1出现的次数,以外原理跟前一行一样。(和上一行有所不同的是,我们可以把&去掉,因为我们知道原始输入8位不可能出现超过8个1因此二进制值不会超过4位。)
    现在我们有一个三十二位数,由四个字节组成,每个字节保存着原始输入中为1的位的数量。(我们把它们称作A,B,C和D。)那么为什么我们用0x01010101乘以这个值(命名为k)?

    由于:

    0x01010101 = (1 << 24) + (1 << 16) + (1 << 8) + 1

    可得:

    k * 0x01010101 = (k << 24) + (k << 16) + (k << 8) + k

    k * 0x01010101最高位就是原始输入的1出现次数的最终结果。>> 24只是简单的将最高位的值移到最低位。


    Redis实现

    BITCOUNT命令的实现用到了查表和variable-precisionSWAR两种算法:

    • 查表算法使用键长为8位的表,表中记录了从0000 0000 到1111 1111在内的所有二进制位的汉明重量。
    • variable-precisionSWAR算法,BITCOUNT命令在每次循环中载入128个二进制位,然后调用四次32位variable-precision算法来计算这128个二进制位的汉明重量。

    程序会根据未处理的二进制位的数量来决定使用哪种算法:
    如果未处理的二进制位数量小于128位,那么程序使用查表法来计算二进制位的汉明重量。否则使用variable-precisionSWAR算法来计算二进制位的汉明重量。

    BITTOP

    因为C语言直接支持对字节执行逻辑与,或,异或,非的操作,所以BITOP的四个操作都是直接基于这些逻辑操作来实现的。
    执行过程:
    1、创建一个空白的位数组value,用于保存逻辑操作的结果;
    2、对两个位数组的每个字节执行逻辑操作,并将结果保存到value[i]字节;
    3、经过前面的逻辑操作,程序得到了计算结果,并将它保存在result上。

    BITTOP AND <result > <operand-1>  [operand-2]

    BITTOP OR <result > <operand-1>  [operand-2]

    BITTOP NOT <result > <operand-1>  [operand-2]

    BITTOP XOR <result > <operand-1>  [operand-2]


     

     

     

    展开全文
  • 十进制与二进制数的相互转换,可以通过移位操作取倒每一位数操作两种方法......
  • 例如,5的二进制形式为101b,有3个二进制位,17的二进制形式为1 0001b,有5个二进制位。问题:已知n∈[0, pow(2, 31) ),求n的二进制位数。 拿到问题后,我在纸上列举了一些例子,以观察规律。例子如下: ...
  • 二进制最低位

    千次阅读 2019-01-20 14:09:48
    杭电1.2.8 Lowest Bit ...amp;sectionid=2&amp;problemid=22 这道题是将十进制写成二进制,然后输出二进制最低位! 例如: 26(10)=11010(2) 输出:2; 88(10)=1011000(2) 输出:8; (最...
  • 1.十进制转化为二进制数 十进制15 上图中箭头的方向即为二进制数中从低位到高位(从右往左)的顺序, 二进制数为:0000 0000 0000 0000 0000 0000 0000 1111 2.十进制转化为八进制 十进制:15 与...
  • 二进制最低位1

    2021-03-16 20:23:50
    学习自如何求一个二进制最低位1在哪里 补码: ① 正数的补码为本身; ② 负数的补码: 例如负数为a,对应正数为b,利用a+b=0 写负数a补码的方法1:先填符号位1,其余位在b的基础上全部取反,再+1 最高位是1,...
  • C语言 打印整数二进制的奇数位和偶数位

    千次阅读 多人点赞 2021-04-28 19:24:28
    获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列 思路分析 打印一个整数的二进制位中的偶数位和奇数位,可以对整数进行移位操作,再将移位的二进制位与1进行&操作。二进制的序列在计算机的...
  • 二进制数与十六进制之间如何互相转换

    千次阅读 多人点赞 2017-04-01 14:12:32
    二进制与十六进制之间的转换与二进制和八进制之间的转换很类似,今天我们来详细看一下:首先,我们来看一下数学关系即24=16,即用四位二进制表示一八进制。 方法/步骤 首先呢,先要看看十六位数...
  • 如果我们要把十进制的150转化为二进制数,可以使用下面两种方法: 第一种方法:表格法 这种方法的核心思想就是用二进制的各位来“拼凑”出我们的十进制。 我们先把二进制各位的权列在表格里面。(我们如何...
  • 然后在结构体描述部分对电路模块的功能进行描述,指明整个电路时如何运作的:对3个二进制的9矢量进行加法运算输出到data。 使用两个四位二进制加法器组成。 功能设计 实现八位二进制数加法,并保存可能存在的...
  • 汇编语言:将ASCⅡ码表示的十进制转换为二进制数/十六进制 你们好! 这是我的第一个汇编程序的博客,汇编是一个神奇的东西,你深入了解他之后会为他着迷的!!! 题目 将ASCⅡ表示的十进制数字转化为二进制数,...
  • 求一个整数的二进制最高位

    千次阅读 2011-03-23 13:42:00
    求十进制整数的最高位非常简单,那计算机如何求一个整数的二进制最高位? <br />众所周知,计算是通过01二进制来表示世界的,自然整数也是使用二进制存储在计算机硬盘中。那如何求一个整数的二进制最高位...
  • 16寄存器实现32位二进制数左移4、 源代码 MOV CL, 04 SHL DX, CL MOV BL, AH SHL AX, CL SHR BL, CL OR DL, BL 说明: MOVCL,04 SHL DX,CL;以上两行指令是把dx左移4,这样dx的最低4为0 MOVBL,AH;...
  • 扩展二进制数

    2017-09-22 09:47:50
    我们都知道二进制数的每一可以是0或1。有一天小Hi突发奇想:如果允许使用数字2会发生什么事情?小Hi称其为扩展二进制数,例如(21)ii = 2 * 21 + 1 = 5, (112)ii = 1 * 22 + 1 * 21 + 2 = 8。 很快小Hi意识...
  • 1.二进制转换为十进制: (11010)2=1x24+1x23+0x22+1x21+0x20=(26)10 2.八进制转十进制: (140)8=1x82+4x81+0x80=(96)10 3.十六进制转十进制: (A2C)16=10x162+2x161+12x160=(2604)16 二、十进制转换为R进制 将...
  • 怎样 获取二进制序列中的奇数位和偶数位? 常见操作符的使用,如:>>、&
  • 建链表:二进制数可用带头结点的单链表存储,第一个节点存储二进制数最高位,依次存储,最后一个节点存储位二进制数最低位二进制数的加法规则:实现二进制数加1运算,方向从最低位往高位找到第一个为0的位,...
  • 整数二进制展开中位1的总数 前言 目前在,额,怎么说呢,回炉重造数据...,网上常见的算法是通过将n二进制展开中的最低位1转置0来统计,此算法本文也会介绍(说是介绍其实是抄书啦),然邓老师书上又介绍了一...
  • 二进制数的表示模式

    2019-08-25 17:56:08
    计算机中的二进制机器分为:有符号数和无符号。 无符号二进制的每一位都代表对应位的数值。 有符号:在有符号中规定最高位来表示数据符号,其中1代表负,0代表正。 真值:把带符号位的机器所对应的...
  • 二进制转换及运算

    千次阅读 2016-02-25 08:53:10
    二进制、八进制、十进制与十六进制,它们之间的区别在于运算时逢几进一。比如说二进制是逢2进一,十进制也就是我们常用的0-9是逢10进一。 ①二进制 1.二进制转十进制:  方法:把二进制数按权展开、想加即...
  • 详解计算机内部存储数据的形式—二进制数 前言 要想对程序的运行机制形成一个大致印象,就要了解信息(数据)在计算机内部是以怎样的形式来表现的,又是以怎样的方法进行运算的。在 C Java 等高级语言编写的 程序...
  • C语言实现二进制数逆序排列 代码实现 test.c #include <math.h> #include <stdio.h> //输入:i 要变序的 m 二进制的位数 //例:若输入为011(十进制为3),则输出为110(十进制为6) int ...
  • 请问,用5写出二进制补码的最高(大)有符号整数(用十进制表示),和最低(小)有符号的整数(用十进制表示),分别是多少?最好有解题过程。谢谢!这是我正在研究的一道题目,请各位帮忙解答。
  • 【问题描述】:获取一个数二进制序列中所有的偶数位和奇数位,分别输出其奇数和偶数的二进制序列。 例如:20的二进制序列00000000000000000000000000010100 偶数序列为:0000000000000000 奇数序列为:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 41,859
精华内容 16,743
关键字:

二进制数的最高位和最低位