今天我继续来分享几个有意思的题目。

题一:

位运算的相关练习题_System

这里所说的奇偶位指的是二进制下的奇偶位。 解析:与运算的运算规则:1&0=0,1&1=1,0&1=0,0&0=0。观察一下我们可以发现,在二进制形式下1与一个数进行与运算的结果就是那个数,而0与一个数进行与运算的结果都是0。如果我们将一个数与10101010.....进行与运算,就会保留该数的偶数位(从右往左),奇数位就会变为0。例如:9的二进制是1001,与1010进行与运算

00001001  9的二进制形式
10101010
————————
1000  9的偶数位分别为0,1
  • 1.
  • 2.
  • 3.
  • 4.

同理如果我们将一个数与010101....进行与运算就会保留该数的奇数位,偶数位都会变成0

00001001  9的二进制形式
01010101
————————
00000001   9的奇数位分别为1,0
  • 1.
  • 2.
  • 3.
  • 4.

如果我们将保留的偶数位填上0右移一位,奇数位添上0左移一位,二者再进行异或运算会发生什么呢

0101  偶数位右移一位——>0010
1010  奇数位左移一位——>0100
                  ——————————进行异或运算
                     0110    可以看出恰好将1001中的奇偶位进行了互换。
                             该数化为十进制为6
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

由于int型的整数最多有32位,所以101010...化为16进制即为0xaaaaaaaa, 0101....化为16进制就会变为0x55555555。该题的代码如下:

import java.util.Scanner;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		System.out.println(change(n));
	}
	public static int change(int n) {
		int ou=n&0xaaaaaaaa;       //获得偶数位,奇数位变为0
		int ji=n&0x55555555;         //获得奇数位,偶数位变为0
		return (ou>>1)^(ji<<1);
	}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

结果如下:

位运算的相关练习题_进制_02

上面这道题的解法可能很难想出来,但是没事,记住这个算法就行。

题二:

位运算的相关练习题_System_03

解析:这道题如果知道浮点数二进制怎么计算的话应该是很简单的,如果不清楚也没事。我下面会给大家解释。给定一个浮点数,将它×2,若结果大于1,将1记下来,并将结果减一,若小于1,就将0记下来,重复这个过程,直到最后的结果为0。如0.625*2=1.25,记下来1,减1后得0.25,0.25*2=0.5,记下来0,0.5*2=1,记下来1,减一后得0,运算结束。然后将记下的结果按顺序拼接得到101,再向前面加0.得到的0.101即为最后的结果。

搞清楚这个原理代码就很简单。

import java.util.Scanner;

public class Two {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		double a=sc.nextDouble();
		StringBuilder s=new StringBuilder();   //由于最后的结果要拼接起来,所以用stringbuilder更简单
		s.append("0.");
		while(a!=0) {   //原来的数为0后,循环结束
			a*=2;
			if(a>=1) {   //去除1
				s.append("1");
				a-=1;
			}else {
				s.append("0");
			}
		}
		if(s.length()>34) {
			System.out.println("ERROR");
		}else {
			System.out.println(s);
		}
	}

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

结果如下:

位运算的相关练习题_进制_04

题三:

位运算的相关练习题_进制_05

解析:这道题的解法有很多种,如果实在想不出来可以直接暴力,但是既然放到这个地方,那肯定不是这么简单的了。先来看一下引例:

如果有两个相同的二进制的数,我们对他们进行不进位的加法计算,比如110和110,由于不进位,
得到的结果就会变成000,怎么来的呢?
110
110
————
000     0与0相加得0,1与1相加得2,余下0,由于不进位,所以只剩下一个0,所以
        得到000,化为10进制为0.
        
同理,如果我们将10个相同得数进行10进制下的不进位加法,那么得到得结果也是0.
说到这里你们可能就会想出什么了,那就是k个相同的数进行k进制的相加,得到的结果
是0.
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

根据上面的推理我们只要将该数组遍历进行k进制的不进位相加就行,最后得到的结果就是答案。 代码如下:

public class Test {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		int[] arr= {1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6};
		char[][] charArr=new char[arr.length][];
		int k=3;
		int maxLen=0;
		//将数字转换为k进制的字符数组并反转
		for(int i=0;i<arr.length;i++) {
			charArr[i]=new StringBuffer(Integer.toString(arr[i],k)).reverse().toString().toCharArray();
		if(maxLen<charArr[i].length) maxLen=charArr[i].length;
		}
		int[] resArr=new int[maxLen];
		//进行不进位加法
		for(int i=0;i<maxLen;i++) {
			for(int j=0;j<arr.length;j++) {
				if(i>=charArr[j].length) resArr[i]+=0;
				else
				resArr[i]+=charArr[j][i]-'0';
			}
		}
		int res=0;
		//将数组转换为十进制
		for(int i=0;i<maxLen;i++) {
			res+=(resArr[i]%k)*(int)Math.pow(k, i);
		}
		System.out.println(res);
	}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

位运算的相关练习题_System_06

这里解释一下代码 先说一下不进位加法。 先把k进制下的每一位存起来,然后将每个数对应的位数相加,再把该数字存到一个新的数组里面,这样就没有进位,只是把这个相加后得到的数字存在了对应下标的数组里面。 这里解释一下为什么要将字符串反转后转换为字符数组。 将数字转换为k进制的字符串后,他会自动去掉高位的0,比如

1的三进制 1
5的三进制12
此时进行不进位相加的话就变成了12
                            1
                            ————
因为我们是按下标的顺序进行相加的,此时2对应的下标为1,而下面的那个1对应的
下标为0,而实际上应该让上面的2与下面的1进行相加,这样就会错位,因此我们
反转后各个下标对应的数字刚好照应。
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

由于是不进位加法,所以我们要将相加之后的数取余。 此外,将原来的字符串反转后对后面的进制转换也有好处,根据进制转换的公式,从低到高位要依次乘进制的0,1,2...次方,我们反转后刚好从低到高,这样就与下标一致,循环计算就会容易。 如果还是不太清楚的话,可以去搜一下不进位加法,或者私聊我。