int中使用的计数位数
如果您有二进制数10110,我怎么能让它返回5? 例如,一个数字告诉我们使用了多少位? 下面列出了一些类似的例子:
- 101应该返回3
- 000000011应该返回2
- 11100应该返回5
- 101010101应该返回9
如何在Java中获得最简单的方法? 我已经提出了以下方法,但我可以更快地完成:
public static int getBitLength(int value) { if (value == 0) { return 0; } int l = 1; if (value >>> 16 > 0) { value >>= 16; l += 16; } if (value >>> 8 > 0) { value >>= 8; l += 8; } if (value >>> 4 > 0) { value >>= 4; l += 4; } if (value >>> 2 > 0) { value >>= 2; l += 2; } if (value >>> 1 > 0) { value >>= 1; l += 1; } return l; }
最简单的?
32 - Integer.numberOfLeadingZeros(value)
如果您正在寻找算法,Java API的实现者同意您的分而治之的位移方法:
public static int numberOfLeadingZeros(int i) { if (i == 0) return 32; int n = 1; if (i >>> 16 == 0) { n += 16; i <<= 16; } if (i >>> 24 == 0) { n += 8; i <<= 8; } if (i >>> 28 == 0) { n += 4; i <<= 4; } if (i >>> 30 == 0) { n += 2; i <<= 2; } n -= i >>> 31; return n; }
编辑 :提醒那些信任浮点计算准确性的人,运行以下测试工具:
public static void main(String[] args) { for (int i = 0; i < 64; i++) { long x = 1L << i; check(x); check(x-1); } } static void check(long x) { int correct = 64 - Long.numberOfLeadingZeros(x); int floated = (int) (1 + Math.floor(Math.log(x) / Math.log(2))); if (floated != correct) { System.out.println(Long.toString(x, 16) + " " + correct + " " + floated); } }
第一个检测到的偏差是:
ffffffffffff 48 49
不幸的是,没有Integer.bitLength()
方法直接给你答案。
BigInteger
一个类似的方法,所以你可以使用那个:
BigInteger.valueOf(value).bitLength()
构造BigInteger
对象会降低效率,但这只会影响数百万次。
您想要计算数字的基数2对数 – 具体来说:
1 +楼(log 2 (价值))
Java有一个使用base e的Math.log方法,所以你可以这样做:
1 + Math.floor(Math.log(value) / Math.log(2))
要小心你的要求。 一种非常快速的技术是进行表查找:
int bittable [] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ... }; int numbits (int v) { return bittable [v]; }
其中bittable
包含每个int的条目。 当然,这会带来负面价值的复杂性。 更实际的方法是计算数字的位域中的位
int bittable [16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; int numbits (int v) { int s = 0; while (v != 0) { s += bittable [v & 15]; v >>= 4; } return s; }
您真的只想找到最高位的位置1.请参阅此页面 ,标题为“查找整数的整数对数基数2(也就是最高位集的位置)”。
从这里开始 ,只需按位和添加即可:
int GetHighestBitPosition(int value) { if (value == 0) return 0; int position = 1; if ((value & 0xFFFF0000) == 0) position += 16; if ((value & 0xFF00FF00) == 0) position += 8; if ((value & 0xF0F0F0F0) == 0) position += 4; if ((value & 0xCCCCCCCC) == 0) position += 2; if ((value & 0xAAAAAAAA) == 0) position += 1; return position; }
我认为该数字的四舍五入的log_2将为您提供所需的内容。
就像是:
return (int)(Math.log(value) / Math.log(2)) + 1;
int CountBits(uint value) { for (byte i = 32; i > 0; i--) { var b = (uint)1 << (i - 1); if ((value & b) == b) return i; } return 0; }
如果你正在寻找最快的(没有一个表,这当然更快),这可能是一个:
public static int bitLength(int i) { int len = 0; while (i != 0) { len += (i & 1); i >>>= 1; } return len; }
Integer.toBinaryString(值)。长度()
另一种解决方案是使用根据API的BitSet
的length()
返回“逻辑大小”…最高设置位的索引…加1。
要使用BitSet
您需要创建一个数组。 所以它并不像从纯int
开始那么简单。 但是你从JDK盒中得到它 – 经过测试和支持。 它看起来像这样:
public static int bitsCount(int i) { return BitSet.valueOf(new long[] { i }).length(); }
应用于问题中的示例:
bitsCount(0b101); // 3 bitsCount(0b000000011); // 2 bitsCount(0b11100); // 5 bitsCount(0b101010101); // 9
在询问位时, BitSet
在我看来是合适的数据结构。