zoukankan      html  css  js  c++  java
  • 位运算的奇巧淫技

    位运算与进制基础

    位运算符

    1.在处理整形数值时,可以直接对组成整形数值的各个位进行操作。这意味着可以使用屏蔽技术获得整数中的各个位。

    2.&(与)、|(或)、^(异或)、~(非/取反)。

    3.>>和<<运算符将二进制位进行右移或者左移操作。

    4.>>>运算符将用0填充高位;>>运算符用符号位填充高位,没有<<<运算符。

    5.对于int型,1<<35与1<<3是相同的,而左边的操作数是long型时需对右侧操作数模64。

    6.与:都为1结果为1;或:有一个为1结果为1,;异或:二者不同时结果为1。

    在这里插入图片描述

    小技巧

    1.判断奇偶数:x&1=1则x是奇数,x&1=0则x是偶数。

    2.获取二进制位是1还是0:x&某一个奇数之后再右移相应的位数。

    3.交换两个整数变量的值。

    4.不用判断语句,求整数的绝对值。

    异或:可以理解为不进位加法:1+1=0,0+0=0,1+0=1。

    性质

    1.交换律可以交换运算因子的位置,结果不变。

    2.结合律(即(a ^ b ) ^ c = = a ^ ( b ^ c ) )

    3.对于任何数x,都有x ^ x = 0 , x ^ 0 = x ,同自己求异或为0,同0求异或为自己。

    4.自反性A ^ B ^ B = A ^ 0 = A,连续和同一个因子做异或运算,最终结果为自己。

    题解

    题1:找出唯一成对的数

    1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?

    思路

    连续异或,消除重复。

    代码

    #include <iostream>
    using namespace std;
    int main()
    {
        int x=0,test[10]={1,2,3,4,5,6,7,8,9,7};
        for (int i = 1; i <= 9; ++i) x=x^i;
        for (int j = 0; j < 10; ++j) x=x^test[j];
        cout<<x<<endl;
        return 0;
    }
    

    题2:找出落单的那个数

    一个数组里处理某一个数之外,其他的数字都出现了两次。请写程序找出这个只出现一次的数字。

    思路

    连续异或,消除重复。

    代码

    #include <iostream>
    using namespace std;
    int main()
    {
        int x=0,test[11]={1,1,3,3,5,5,7,7,9,9,11};
        for (int j = 0; j < 11; ++j) x=x^test[j];
        cout<<x<<endl;
        return 0;
    }
    

    题3:二进制中1的个数

    请实现一个函数,输入一个整数,输出该数二进制表示中的1的个数。
    例:9的二进制表示为1001,有2位是1.

    思路

    1.整数x与1,然后将1循环左移32次;
    2.整数x与1,然后将x循环右移32次;
    3.x&(x-1)可以消掉最右边的1,直到x=0。

    代码

    #include <iostream>
    using namespace std;
    int main()
    {
        int x,n=1,ans=0;
        cin>>x;
        for (int i = 0; i < 32; ++i)
            if (x&(n<<i)) ans++;
        cout<<ans<<endl;
        return 0;
    }
    
    #include <iostream>
    using namespace std;
    int main()
    {
        int x,ans=0;
        cin>>x;
        for (int i = 0; i < 32; ++i)
            if ((x>>i)&1) ans++;
        cout<<ans<<endl;
        return 0;
    }
    
    #include <iostream>
    using namespace std;
    int main()
    {
        int x,ans=0;
        cin>>x;
        while (x)
        {
            x=x&(x-1);
            ans++;
        }
        cout<<ans<<endl;
        return 0;
    }
    

    题4:是不是2的整数次方

    用一条语句判断一个整数是不是2的整数次方。

    思路

    2的整数次方说明x中只有一个1,x&(x-1)可以消掉最右边的1。

    代码

    #include <iostream>
    using namespace std;
    int main()
    {
        int x;
        cin>>x;
        if ((x&(x-1))==0) cout<<"yes"<<endl;
        else cout<<"no"<<endl;
        return 0;
    }
    

    题5:将整数的奇偶位互换

    输入一个整数,将其二进制形式的奇偶位置数互换。

    思路

    一个数&(0101)×8得到的是它的所有奇数位数字,&(1010)×8得到的是它所有偶数位数字,然后分别左移和右移之后再异或一下,得到的就是奇偶位互换的数字。

    代码

    #include <iostream>
    using namespace std;
    int main()
    {
        int x;
        cin>>x;
        int ji=0x55555555,ou=0xaaaaaaaa;
        int a=x&ji,b=x&ou,c=(a<<1)^(b>>1);
        cout<<c<<endl;
        return 0;
    }
    

    题6:0~1间浮点实数的二进制表示

    给定一个介于0和1之间的实数,(如0.625),类型为double,打印它的二进制表示(0.101,因为小数点后的二进制分别表示0.5,0.25,0.123…)。
    如果该数字无法精确地用32位以内的二进制表示,则打印“ERROR”

    思路

    浮点数转换为二进制的方式为乘2挪整。

    代码

    #include <iostream>
    #include <cstring>
    using namespace std;
    int main()
    {
        string s;
        int len=0;
        double x;
        cin>>x;
        while (x>0)
        {
            double num=x*2;
            if (num>=1.0)
            {
                s+='1';
                x=num-1;
            }
            else
            {
                s+='0';
                x=num;
            }
            len++;
            if (len>32)
            {
                cout<<"ERROR"<<endl;
                return 0;
            }
        }
        cout<<"0."<<s<<endl;
        return 0;
    }
    

    题7:出现k次与出现1次

    数组中只有一个数出现了1次,其它的数都出现了k次,请输出只出现了1次的数。

    思路

    k个相同的k进制数做不进位加法结果为0。

  • 相关阅读:
    Centos7 禁止firewalld并使用iptables 作默认防火墙
    在Kibana上格式化字段,更好的在dashboard上展示
    利用 ELK系统分析Nginx日志并对数据进行可视化展示
    Nginx 服务器开启status页面检测服务状态
    Linux 上通过binlog文件 恢复mysql 数据库详细步骤
    Linux 为FTP 服务器添加iptables规则--案例分析
    NUMA架构的CPU -- 你真的用好了么?
    Linux 上利用Nginx代理uWSGI处理Flask web应用
    Linux 之不同运维人员共用root 账户权限审计
    Strategy
  • 原文地址:https://www.cnblogs.com/AlexKing007/p/12338452.html
Copyright © 2011-2022 走看看