• 判断无符号整数的二进制形式中是否包含偶数个1


    题目要求:若二进制无符号整数x包含偶数个1,返回1,否则返回0.

    要求:只能使用位运算、加减法和==、!=,最多包含12个算术运算、位运算和逻辑运算,可以假设sizeof(unsigned)==4

    不能使用乘除模运算,不能使用条件分支,循环,函数调用,大小比较等(详见《深入理解计算机系统》第二章习题)

    首先,最朴素最直接的方法——一位一位统计肯定次数远远多于12次.

    考虑:异或运算(^)可以保持两个操作数1的个数的奇偶性.

    因为两个操作数,一1一0,结果为1,1的个数还是奇数;两0,结果为0,不影响,两1,结果为0,1的个数还是偶数.

    这样,想到了降量的思想,把判断32位数转化为16位,然后依次进行.

    先开始想的是分别取到前/后16位,然后异或:

    1.x&0xFFFF0000;

    2.x&0x0000FFFF;

    3.将步骤1得到的结果向右移16位;

    4.将2和3的结果异或.

    4得到的结果和原32位数1的个数的奇偶性一致.

    但是需要4*5+1(根据要求取反)=21步.

    简化一下,1和3可以通过x/65536这一步得到,这样,需要步数是3*5+1=16步,还是超出了要求.

    仔细想想,将x和x/65536异或,得到结果前16位和原x前16一致,但是后16位1的个数奇偶性与原x二进制1的个数奇偶性一致.

    这样,两步完成32位到16位的简化,2*5=10次之后,得到结果前面31位不用管,最后1位说明了奇偶性.

    这时,把结果模2,得到最后1位,0或者1.

    然后取反,得到题目要求的结果.总共需要12步.

    用C++(底层数据的表示和C一样)写了一段程序并简单测试了一下.

    下面附上源码,一共使用6次算术运算,5次位运算和1次逻辑运算.

    代码如下:

    nt even_ones(unsigned x )  
    {  
        unsigned x16 = (x>>16)^x;  
        unsigned x8 = (x16>>8)^x16;  
        unsigned x4 = (x8>>4)^x8;  
        unsigned x2 = (x4>>2)^x4;  
        unsigned x1 = (x2>>1)^x2;  
        return (~x1)&0x1;  
    } 
    
    int main()
    {
        unsigned a;
        scanf("%u",&a);
        int ret=even_ones(a);
    
        printf("%d",ret);
    } 

    参考:http://blog.csdn.net/zhzhanp/article/details/6324511

  • 相关阅读:
    视图&索引&序列
    PL/SQL语言基础
    C#实现递归矩阵连乘(动态规划的递归自顶向下,非递归自地向上)
    JS 第五课
    请问,小丽的鞋子到底是什么颜色的?
    用10!来回顾 PL/SQL语言基础 && 标准异常名
    SELECT 查询—子查询
    备份和恢复
    JS 第六课
    Linux学习之二Linux系统的目录结构
  • 原文地址:https://www.cnblogs.com/youxin/p/3234094.html
Copyright © 2020-2023  润新知