题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制是1001,有2位是1。所以若是输入9,该函数输出2。函数
一个基本的思路:先判断整数二进制表示中最右边一位是否是1。接着把输入的整数右移一位,此时原来处于从右边数起的第二位被移到最右边了,再判断是否是1。这样每次移动一位,直到整个整数变成0为止。单元测试
怎么判断一个整数的最右边是否是1:只要把整数和1作位与运算看结果是否是0就知道了。测试
public static int NumberOf1Solution1(int n) { int count = 0; while (n > 0) { if ((n & 1) == 1) { count++; } n = n >> 1; } return count; }
PS:右移运算符m>>n表示把m右移n位。右移n位的时候,最右边的n位将被丢弃。若是数字原先是一个正数,则右移以后在最左边补n个0;若是数字原先是负数,则右移以后在最左边补n个1。例以下面对两个八位二进制数进行右移操做:ui
00001010>>2=00000010spa
10001010>>3=11110001code
那么,问题来了:上面的方法若是输入一个负数,好比0x80000000,若是一直作右移运算,最终这个数字就会变成0xFFFFFFFF而陷入死循环。blog
为了不死循环,咱们能够不右移输入的数字i:get
(1)首先把i和1作与运算,判断i的最低位是否是为1。博客
(2)接着把1左移一位获得2,再和i作与运算,就能判断i的次低位是否是1。it
(3)这样反复左移,每次都能判断i的其中一位是否是1。
public static int NumberOf1Solution2(int n) { int count = 0; uint flag = 1; while (flag >= 1) { if ((n & flag) > 0) { count++; } flag = flag << 1; } return count; }
PS:这个解法中循环的次数等于整数二进制的位数,32位的整数须要循环32次。
把一个整数减去1,再和原整数作与运算,会把该整数最右边一个1变成0。那么一个整数的二进制表示中有多少个1,就能够进行多少次这样的操做。
public static int NumberOf1Solution3(int n) { int count = 0; while (n > 0) { count++; n = (n - 1) & n; } return count; }
PS:把一个整数减去1以后再和原来的整数作位与运算,获得的结果至关因而把整数的二进制表示中的最右边一个1变成0。不少二进制的问题均可以用这个思路解决。
// 输入0,期待的输出是0 [TestMethod] public void NumberOfOneInBinaryTest1() { Assert.AreEqual(BinaryHelper.NumberOf1Solution2(0),0); Assert.AreEqual(BinaryHelper.NumberOf1Solution3(0),0); } // 输入1,期待的输出是1 [TestMethod] public void NumberOfOneInBinaryTest2() { Assert.AreEqual(BinaryHelper.NumberOf1Solution2(1), 1); Assert.AreEqual(BinaryHelper.NumberOf1Solution3(1), 1); } // 输入10,期待的输出是2 [TestMethod] public void NumberOfOneInBinaryTest3() { Assert.AreEqual(BinaryHelper.NumberOf1Solution2(10), 2); Assert.AreEqual(BinaryHelper.NumberOf1Solution3(10), 2); } // 输入0x7FFFFFFF,期待的输出是31 [TestMethod] public void NumberOfOneInBinaryTest4() { Assert.AreEqual(BinaryHelper.NumberOf1Solution2(0x7FFFFFFF), 31); Assert.AreEqual(BinaryHelper.NumberOf1Solution3(0x7FFFFFFF), 31); } // 输入0xFFFFFFFF(负数),期待的输出是32 [TestMethod] public void NumberOfOneInBinaryTest5() { Assert.AreEqual(BinaryHelper.NumberOf1Solution2(0xFFFFFFFF), 32); Assert.AreEqual(BinaryHelper.NumberOf1Solution3(0xFFFFFFFF), 32); } // 输入0x80000000(负数),期待的输出是0 [TestMethod] public void NumberOfOneInBinaryTest6() { Assert.AreEqual(BinaryHelper.NumberOf1Solution2(0x80000000), 0); Assert.AreEqual(BinaryHelper.NumberOf1Solution3(0x80000000), 0); }
(1)测试经过状况:
(2)代码覆盖率: