`

6 种 求二进制数中1的个数 算法 java 实现

阅读更多
package BitCount;

/**
 * 任意给定一个32位无符号整数n,求n的二进制表示中1的个数,比如n = 5(0101)时,返回2,n = 15(1111)时,返回4
 * 
 * @author vivizhyy
 * 
 */
public interface BitCountMethods {

	/** 移位+计数 */
	public int normal(int x);

	/** 不断清除x的二进制表示中最右边的1,同时累加计数器,直至x为0 */
	public int quick(int x);

	/**
	 * @see #static8bit(int)
	 */
	public int static4bit(int x);

	/**
	 * 首先构造一个包含256个元素的表table,table[i]即i中1的个数,这里的i是[0-255]之间任意一个值。
	 * 然后对于任意一个32bit无符号整数n
	 * ,我们将其拆分成四个8bit,然后分别求出每个8bit中1的个数,再累加求和即可,这里用移位的方法,每次右移8位
	 * ,并与0xff相与,取得最低位的8bit
	 * ,累加后继续移位,如此往复,直到n为0。所以对于任意一个32位整数,需要查表4次。以十进制数2882400018为例
	 * ,其对应的二进制数为10101011110011011110111100010010
	 * ,对应的四次查表过程如下:红色表示当前8bit,绿色表示右移后高位补零。
	 * 
	 * 第一次(n & 0xff) 10101011110011011110111100010010
	 * 
	 * 第二次((n >> 8) & 0xff) 00000000101010111100110111101111
	 * 
	 * 第三次((n >> 16) & 0xff)00000000000000001010101111001101
	 * 
	 * 第四次((n >> 24) & 0xff)00000000000000000000000010101011
	 */
	public int static8bit(int x);

	/** 先将n写成二进制形式,然后相邻位相加,重复这个过程,直到只剩下一位。 
	 * 1 1  0 1  1 0  0 1
	 * \ /  \ /  \ /  \ /
	 *  2    1    1    1
	 *  \    /     \   /
	 *     3         2
	 *     \        /
	 *          5
	 */
	public int parallel(int x);
	
	/** http://www.cnblogs.com/graphics/archive/2010/06/21/1752421.html */
	public int perfectness(int x);

}

 

package BitCount;

public class BitCounts implements BitCountMethods {

	@Override
	public int normal(int x) {
		int c = 0;
		for (; x > 0; x >>>= 1) {
			c += x & 1; // 如果当前位是 1,计数器加 1
		}
		return c;
	}

	@Override
	public int quick(int x) {
		int c = 0;
		for (; x > 0; c++) {
			x &= (x - 1); // 清除最右边的 1
		}
		return c;
	}

	@Override
	public int static4bit(int x) {
		int[] table = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
		int c = 0;
		for (; x > 0; x >>>= 4) {
			c += table[x & 0xF];
		}

		return c;
	}

	@Override
	public int static8bit(int x) {
		int[] table = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2,
				2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3,
				4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,
				4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2,
				3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4,
				4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5,
				6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
				2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3,
				4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5,
				5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5,
				6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5,
				4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5,
				6, 6, 7, 6, 7, 7, 8, };
		int c = 0;
		for(; x > 0; x >>>= 8){
			c += table[x & 0xFF];
		}
		
		return c;
	}

	@Override
	public int parallel(int x) {
		// 0x55 = 0101 0101
		x = (x & 0x55555555) + ((x >>> 1) & 0x55555555);
		//0x33 = 0011 0011
		x = (x & 0x33333333) + ((x >>> 2) & 0x33333333);
		//0x0f = 0000 1111
		x = (x & 0x0f0f0f0f) + ((x >>> 4) & 0x0f0f0f0f);
		//0x00ff = 0000 0000 1111 1111
		x = (x & 0x00ff00ff) + ((x >>> 8) & 0x00ff00ff);
		//0x0000ffff = 0000 0000 0000 0000 1111 1111 1111 1111
		x = (x & 0x0000ffff) + ((x >>> 16) & 0x0000ffff);
		
		return x;
	}

	@Override
	public int perfectness(int x) {
		int temp = x - (x >>> 1) & 033333333333 - (x >>> 2) & 011111111111;
		return (temp +(temp >>>3)) & 030707070707 % 63;
	}


}

 

package BitCount;

import static org.junit.Assert.*;

import org.junit.Test;

public class BitCountMethodsTest {
	BitCountMethods bcm = new BitCounts();
	int x = 123;

	@Test
	public final void testNormal() {
		assert(bcm.normal(x) == 6);
	}

	@Test
	public final void testQuick() {
		assert(bcm.quick(x) == 6);
	}

	@Test
	public final void testStatic4bit() {
		assert(bcm.static4bit(x) == 6);
	}

	@Test
	public final void testStatic8bit() {
		assert(bcm.static8bit(x) == 6);
	}

	@Test
	public final void testParallel() {
		assert(bcm.parallel(x) == 6);
	}

	@Test
	public final void testPerfectness() {
		assert(bcm.perfectness(x) == 6);
	}

}
 

 

分享到:
评论

相关推荐

    (android demo)算法实现:计算十进制数N的二进制形式中包含数字1的个数

    在Android开发中,我们经常会遇到各种算法挑战,其中之一就是如何计算一个十进制数N的二进制表示中“1”的个数。这个任务看似简单,但其实涉及到计算机科学的基础知识,包括二进制转换、位操作以及算法设计。下面...

    统计整数的二进制表示形式中有几个1(java实现)

    统计整数的二进制表示形式中有几个1(java实现),代码中有三种方法,分别是利用除、余的方法,位运算,以及利用“与”运算的方法。其中第三种方法效率最高,二进制数中有几个1,算法中的循环内的运算就执行几次。

    A11Might#easyalgorithm#AcWing 801. 二进制中1的个数1

    801. 二进制中1的个数算法:#位运算每次减去给定整数 x 二进制中的最后一位 1(lowbit(n) = n & -n),一共能减几次 x 二进制中就有几个

    二进制串模糊搜索的Java实现0.11

    本文将深入探讨二进制串模糊搜索的Java实现,基于标题"二进制串模糊搜索的Java实现0.11",以及描述中提及的链接,我们能够推断出这是关于一种特定算法的实现,该算法可能基于SimHash,一种常用于相似性检测的技术。...

    java中实现递归计算二进制表示中1的个数

    在Java编程中,计算一个整数在二进制表示中1的个数是一个常见的问题,尤其在面试中经常被用来考察候选人的逻辑思维和算法理解能力。这个问题可以通过两种主要方法解决:迭代和递归。这里我们关注的是递归方法,它能...

    数字调制信号:4FSK,2PSK,数字调制信号在二进制时有基本格式,Java源码.zip

    4FSK是一种基于频率变化的调制方法,其中载波频率在四个不同的离散状态之间切换,以代表二进制数据流中的0或1。4FSK通常用于数据传输,如无线鼠标、键盘和某些无线电通信。4FSK的优势在于其良好的抗噪声性能,因为...

    Java数据结构及算法实例:快速计算二进制数中1的个数(Fast Bit Counting)

    总结来说,Java数据结构及算法实例:快速计算二进制数中1的个数,通过使用Brian Kernighan的位操作技巧,可以高效地计算出整数的二进制表示中1的个数,这对于理解和优化计算密集型代码非常重要。

    JAVA语言实现的遗传算法

    在Java实现中,可以创建一个表示二进制串的类,包含生成、交叉、变异的方法,并在主循环中不断更新种群,直到找到满足条件的解或者达到预设的迭代次数。 **总结** 遗传算法结合Java语言,可以构建出高效且易于维护...

    利用JAVA,求数字特征值。

    在给定的标题“利用JAVA,求数字特征值”中,我们可以理解为使用Java编程语言来实现一种方法,该方法能够计算数字的特定属性或特征。描述提到“奇偶特征是一种简单的特征值”,这暗示了我们可能会探讨如何通过Java...

    CheckSum 十六进制 奇偶校验

    在描述中提到的"对十六进制字符串进行奇偶校验",意味着我们需要计算一个由十六进制数字组成的字符串中,转换为二进制后1的个数,并根据这个数量设置一个奇偶校验位。例如,如果十六进制字符串为"ABCD",转换成二...

    算法-数1的个数(信息学奥赛一本通-T1095).rar

    3. **库函数法**:某些编程语言如C++的`std::bitset`或者Java的`Integer.bitCount()`提供了内置函数,可以直接计算一个整数的二进制表示中1的个数,非常方便,但需要了解和记住这些库函数。 4. **人口普查位法...

    java递归算法

    对于奇数,其1的个数等于该数除以2的二进制表示中的1的个数加1。代码中包含了两种递归实现。 - 第一个实现: - `getBinary(13)`,调用 `getBinary(6)` 并加1 - `getBinary(6)`,调用 `getBinary(3)` 并加1 - `...

    java中的哈希算法和hashcode深入讲解1

    哈希算法可以将任意长度的二进制值映射为较短的、固定长度的二进制值,这个二进制值称为哈希值。 哈希值具有以下几个特点: * 哈希值是二进制值 * 哈希值具有一定的唯一性 * 哈希值极其紧凑 * 要找到生成同一个...

    java代码-任意给出一个十进制整数,将十进制整数转换为二进制数。

    Java作为一种广泛使用的编程语言,提供了多种方法来实现十进制整数到二进制数的转换。本文将深入探讨如何使用Java进行这种转换,以及相关的编程概念。 首先,让我们了解基础概念。十进制(Decimal)是我们日常生活...

    用循环求 任意一个int类型的数字里面含有多少个 1.

    在计算机科学与编程领域中,经常需要对二进制数据进行操作,比如统计一个整数(int类型)中的二进制位中1的个数。这种需求在算法设计、密码学、硬件设计等领域中十分常见。下面我们将详细介绍如何使用Java语言实现这...

    文档指纹Java实现

    4. **计算汉明距离**:对于每个单词,根据其在文档中的正负出现情况,构造一个二进制签名。然后,计算所有单词签名的汉明距离,并取平均值,得到文档的SimHash值。汉明距离表示两个字符串对应位置上不同字符的个数。...

    【华为OD机试真题2023JAVA&JS】不含101的数

    左子树是i-1位二进制数,不含101的个数为dp[i-1]。右子树是i-3位二进制数,不含101的个数为dp[i-3]。然后,我们需要减去左子树的右子树,因为右子树的根节点肯定是1,右子树的左子树的根节点肯定是0,而右子树的左...

    JAVA基于纠错码的冗余技术的研究EVENODD码的设计与实现(源代码)

    在JAVA编程语言中实现EVENODD码,首先需要理解数据的二进制表示,并设计算法来计算校验位。这通常涉及到位运算,如按位与(&)、按位异或(^)和按位或(|)。实现步骤如下: 1. **数据预处理**:将输入的字符或...

Global site tag (gtag.js) - Google Analytics