zoukankan      html  css  js  c++  java
  • [位操作]位操作有关的算法设计

    在进行位操作算法设计之前,先了解位操作的一些细节知识点:

    1. 位操作数据溢出的结果

    2. 数据位提升的隐式转换

    统计一个int类型整数对应的二进制数的1的个数:

    int  NumberOf1Bits(int n)
    {
    	int cnt = 0;
    	
    	while(n != 0)
    	{
    		cnt++;
    		n = n & (n - 1);
    	}
    	return cnt;
    }
    

      分析一个这个程序,如果这个n是正数,没问题,最后肯定能到0,终止循环。但是对于一个负数,它能终止退出循环吗?答案是可以的。因为这个负数一个跟n-1做按位与操作,那么1的个数会一直减少,知道最后变成10000...0000这样的形式,也就是int能表示的最小的负数,n-1得到的结果就是0111...111变成了最大的正数,两个东西按位与得到的结果就是零,这个样子就结束了循环。

    这个问题还有另外的一种解法,那就是移位:

    int  NumberOf1Bits(int n) 
    {
    	int cnt = 0;
     
    	for(int i = 0; i < 32; i++)
    	{
    		cnt += (n & 1);
    		n = (n >> 1);
    	}
    	return cnt;
    }
    

    判断一个数是不是2的幂:

    这个题目首先把负数排除在外,一个负数绝对不是2的幂。在来总结2的幂的数的特征:

    1     2       4         8         16   ....

    1    10    100    1000    10000   ....

    特征就是在某一位中只有一个1,所以可以统计这个数字的1的个数,判断是不是2的幂。

    bool isPowerOfTwo(int n) 
    {
    	int cnt = 0;
    	while(n > 0)
    	{
    		cnt++;
    		n = n & (n - 1);
    	}
    	return cnt == 1;
    }
    

      当然利用移位的方式计算1的个数一样可行,这里还有一个简单的方法。看这些数字的特征是都只有一个1,那么它们和n-1按位与的结果一定是0。所以:

    bool isPowerOfTwo(int n) 
    {
    	return (n > 0) && !(n & (n - 1));
    }
    

      

    逆序一个无符号整数数的各个bit位,得到一个新的无符号数:

    uint32_t reverseBits(uint32_t n) 
    {
    	uint32_t res = 0;
    	for(int i = 0; i < 32; i++)
    	{
    		if(n & 1 == 1)
    		{
    			res = (res << 1) + 1;
    		}//if
    		else
    		{
    			res = res << 1;
    		}//else
    		
    		n = n >> 1;
    	}//for
    	
    	return res;
    }
    

      这个算法就是利用了按位与的相关知识点。

     逆序一个整型int:

    算法的思想类似bit位的逆序,但是要考虑好负数与数据溢出的风险。

    int reverse(int x) 
    {
    	int d = 0;
    	int res = 0;
    	
    	while(x != 0)
    	{
    		if(abs(res) > INT_MAX / 10)
    			return 0;
    		d = x % 10;
    		res = res * 10 + d;
    		x = x / 10;
    	}
    	
    	return res;
    }
    

    由于负数在求mod和除法的时候,符号是保留不变的,所以不用单独的考量负数的问题。但是在检验数据溢出的时候,不能等溢出了在去检测,要在还未溢出但是下次就要溢出时检测,返回0。

    不用四则运算的加法

    这里我们首先得到一个规律:对于数字的运算,除了四则运算,就是位运算了

    题目描述:

    给出两个整数a和b, 求他们的和, 但不能使用 + 等数学运算符。
    

    不能用四则运算,那么就只剩下位运算了。

    接下来借鉴计算机组成原理的加法运算器的工作原理来看。真正的加法运算可以分解为三个步骤:

    1. 不考虑进位的加法运算,当然这种运算可以用按位异或运算代替。
    
    2. 计算每一位的进位值,因为每一个进位都是往高位进一位,所以向左移动一位。
    
    3. 把上面得到的两个结果相加,类似于一个递归的过程。
    

      所以代码实现:

    int aplusb(int nums1, int nums2) 
    {
    	// write your code here, try to do it without arithmetic operators.
    	int sum = 0;
    	int carry = 0;
    	
    	do
    	{
    		sum = nums1 ^ nums2;
    		carry = (nums1 & nums2) << 1;
    		
    		nums1 = sum;
    		nums2 = carry;
    	}while(nums2 != 0);
    	
    	return nums1;
    }
    

      

  • 相关阅读:
    Oracle:ORA-12154: TNS:could not resolve the connect identifier specified
    asp.net mvc4 controller
    asp.net MVC4 学习(一)
    Nuget用法
    asp.net mvc4 新特性
    arcgis for silverlight 相关学习资料整理
    (转)ASP.NET 4.0 尚未在 Web 服务器上注册
    EasyUI TreeGrid
    CollabNetSubversionEdge 4.0.4教程
    C# 混淆 反编译
  • 原文地址:https://www.cnblogs.com/stemon/p/4594428.html
Copyright © 2011-2022 走看看