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开发中,我们经常会遇到各种算法挑战,其中之一就是如何计算一个十进制数N的二进制表示中“1”的个数。这个任务看似简单,但其实涉及到计算机科学的基础知识,包括二进制转换、位操作以及算法设计。下面...
统计整数的二进制表示形式中有几个1(java实现),代码中有三种方法,分别是利用除、余的方法,位运算,以及利用“与”运算的方法。其中第三种方法效率最高,二进制数中有几个1,算法中的循环内的运算就执行几次。
801. 二进制中1的个数算法:#位运算每次减去给定整数 x 二进制中的最后一位 1(lowbit(n) = n & -n),一共能减几次 x 二进制中就有几个
本文将深入探讨二进制串模糊搜索的Java实现,基于标题"二进制串模糊搜索的Java实现0.11",以及描述中提及的链接,我们能够推断出这是关于一种特定算法的实现,该算法可能基于SimHash,一种常用于相似性检测的技术。...
在Java编程中,计算一个整数在二进制表示中1的个数是一个常见的问题,尤其在面试中经常被用来考察候选人的逻辑思维和算法理解能力。这个问题可以通过两种主要方法解决:迭代和递归。这里我们关注的是递归方法,它能...
4FSK是一种基于频率变化的调制方法,其中载波频率在四个不同的离散状态之间切换,以代表二进制数据流中的0或1。4FSK通常用于数据传输,如无线鼠标、键盘和某些无线电通信。4FSK的优势在于其良好的抗噪声性能,因为...
总结来说,Java数据结构及算法实例:快速计算二进制数中1的个数,通过使用Brian Kernighan的位操作技巧,可以高效地计算出整数的二进制表示中1的个数,这对于理解和优化计算密集型代码非常重要。
在Java实现中,可以创建一个表示二进制串的类,包含生成、交叉、变异的方法,并在主循环中不断更新种群,直到找到满足条件的解或者达到预设的迭代次数。 **总结** 遗传算法结合Java语言,可以构建出高效且易于维护...
在给定的标题“利用JAVA,求数字特征值”中,我们可以理解为使用Java编程语言来实现一种方法,该方法能够计算数字的特定属性或特征。描述提到“奇偶特征是一种简单的特征值”,这暗示了我们可能会探讨如何通过Java...
在描述中提到的"对十六进制字符串进行奇偶校验",意味着我们需要计算一个由十六进制数字组成的字符串中,转换为二进制后1的个数,并根据这个数量设置一个奇偶校验位。例如,如果十六进制字符串为"ABCD",转换成二...
3. **库函数法**:某些编程语言如C++的`std::bitset`或者Java的`Integer.bitCount()`提供了内置函数,可以直接计算一个整数的二进制表示中1的个数,非常方便,但需要了解和记住这些库函数。 4. **人口普查位法...
对于奇数,其1的个数等于该数除以2的二进制表示中的1的个数加1。代码中包含了两种递归实现。 - 第一个实现: - `getBinary(13)`,调用 `getBinary(6)` 并加1 - `getBinary(6)`,调用 `getBinary(3)` 并加1 - `...
哈希算法可以将任意长度的二进制值映射为较短的、固定长度的二进制值,这个二进制值称为哈希值。 哈希值具有以下几个特点: * 哈希值是二进制值 * 哈希值具有一定的唯一性 * 哈希值极其紧凑 * 要找到生成同一个...
Java作为一种广泛使用的编程语言,提供了多种方法来实现十进制整数到二进制数的转换。本文将深入探讨如何使用Java进行这种转换,以及相关的编程概念。 首先,让我们了解基础概念。十进制(Decimal)是我们日常生活...
在计算机科学与编程领域中,经常需要对二进制数据进行操作,比如统计一个整数(int类型)中的二进制位中1的个数。这种需求在算法设计、密码学、硬件设计等领域中十分常见。下面我们将详细介绍如何使用Java语言实现这...
4. **计算汉明距离**:对于每个单词,根据其在文档中的正负出现情况,构造一个二进制签名。然后,计算所有单词签名的汉明距离,并取平均值,得到文档的SimHash值。汉明距离表示两个字符串对应位置上不同字符的个数。...
左子树是i-1位二进制数,不含101的个数为dp[i-1]。右子树是i-3位二进制数,不含101的个数为dp[i-3]。然后,我们需要减去左子树的右子树,因为右子树的根节点肯定是1,右子树的左子树的根节点肯定是0,而右子树的左...
在JAVA编程语言中实现EVENODD码,首先需要理解数据的二进制表示,并设计算法来计算校验位。这通常涉及到位运算,如按位与(&)、按位异或(^)和按位或(|)。实现步骤如下: 1. **数据预处理**:将输入的字符或...