- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这个问题是相关的to但在理解代码的实际工作方式上是不同的。更准确地说,我不明白 numberOfTrailingZeros(int i) 在 java 8 here 中的表现如何计算最终结果。代码如下
public static int numberOfTrailingZeros(int i) {
// HD, Figure 5-14
int y;
if (i == 0) return 32;
int n = 31;
y = i <<16; if (y != 0) { n = n -16; i = y; }
y = i << 8; if (y != 0) { n = n - 8; i = y; }
y = i << 4; if (y != 0) { n = n - 4; i = y; }
y = i << 2; if (y != 0) { n = n - 2; i = y; }
return n - ((i << 1) >>> 31);
}
现在我明白了从 16 到 2 的移位操作的目的,但是 n 不会在最后一次移位操作时已经有尾随零的数量:
y = i << 2; if (y != 0) { n = n - 2; i = y; }.
那是我不明白这一行的目的
n - ((i << 1) >>> 31);
为什么当 n
已经有正确的值时我们还需要它?
任何人都可以详细说明发生了什么吗?
谢谢!
最佳答案
我将尝试解释该算法。它有点优化,但我将从(希望)更简化的方法开始。
用于判断一个32位数字的尾随零位的个数,即右边有多少个零(假设最高位在左边)。主要思想是将字段分成两半:如果右半部分全为零,我们将右半部分的位数添加到结果中并继续检查左半部分(再次将其除以);如果右边的不全为零,我们可以忽略左边的,继续检查右边的(结果什么都不加)。
示例:0000 0000 0000 0010 0000 0000 0000 0000
( 0x0002 0000
)
第一步(不是java代码,所有数字都以2为底,结果是十进制):
i = 0000 0000 0000 0010 0000 0000 0000 0000
left = 0000 0000 0000 0010
right = 0000 0000 0000 0000
result = 0
由于右边为零,我们将结果加 16(右边部分的实际位数)并继续检查左边部分
第二步:
i = 0000 0000 0000 0010 // left from previous
left = 0000 0000
right = 0000 0010
result = 16
现在右边不为零,所以我们不向结果添加任何内容并继续右边的部分
第三步:
i = 0000 0010 // right from previous
left = 0000
right = 0010
result = 16
右边不为零,没有添加任何结果,继续右边的部分
第四步:
i = 0010 // right from previous
left = 00
right = 10
result = 16
第五步:
i = 10 // right from previous
left = 1
right = 0
result = 16
现在右边是零,所以我们加 1(右边部分的位数)并且没有其他东西可以除(即原始代码的 return
行)
result = 17
优化:该算法不再有左右部分,而是只检查数字的最左边 x 位,如果右边不为零,则将右边部分移到左边,例如第一步:
y = i << 16; if (y != 0) { ... i = y;}
并且,为了避免出现 else
部分(我认为),它以 31
开始结果(所有部分长度的总和 1+2+4+8+16
),如果右侧(在移动现在左边的部分之后)不为零,则减去位数。再次为第一步:
y = i << 16; if (y != 0) { n = n - 16; ....}
第二次优化,最后一步,代替
y = i << 1; if (y != 0) { n = n - 1; /* i = y not needed since we are done*/ }
return n;
它只是
return n - ((i << 1) >>> 31);
在这里((i << 1) >>>31)
正在移动 i
的第二位(最左第二位,第二高位)到最左边的位置(消除第一位),然后将其移到最右边的位置,也就是说,如果第二位为零,则结果为 0,否则为 1。然后从结果中减去它(从头开始撤消总和 31
)。
第一个(最左边的)位不需要直接检查。仅当所有其他位都为零时才重要,即数字为 0
, 在最开始检查 ( if (i == 0) return 32;
) 或者是 -1
在这种情况下,初始值为 result
返回:31
.
关于java - Integer.numberOfTrailingZero(int i) 如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57429500/
我正在尝试执行 JavaPairRDD 和 JavaPairRDD 的 leftOuterJoin> 并且函数签名返回类型是 JavaPairRDD>>> 这里可选的是 com.google.comm
我正在尝试按元素的频率对元素进行排序 import java.io.BufferedReader; import java.io.IOException; import java.io.InputSt
这个问题已经有答案了: Is List a subclass of List? Why are Java generics not implicitly polymorphic? (19 个回答) 已
编辑:问题已解决:请参阅 Karim SNOUSSI 的答案和我在下面的评论。 这是我在堆栈溢出时遇到的第一个问题,所以我可能不会一开始就把所有事情都做对。对此感到抱歉。此外,我对 Java 和一般
#include #include using namespace std; class Integer { public: int i; Integer (int ll
我不明白: ArrayList list = new ArrayList(); Collection list1 = new ArrayList(); 类 ArrayList扩展实现接口(interf
我编写了:。它成功了。我不知道为什么?
我编写了:。它成功了。我不知道为什么
我编写了:。它成功了。我不知道为什么?
Collectors.counting()返回 long此方法中每个键的值: private static Map countDuplicates(HashSet cards) { retur
我正在尝试通过搜索旧元素并将其替换为新元素来更新节点的元素。但是有一个我不明白的错误。是什么导致我的代码出现该错误,我该如何解决?错误; The method update(Integer, Inte
我有一个称为 client 的表,其中有一列称为created_time ,所以实际上我想绘制一个 map ,以便我可以知道在哪一年和哪一个月添加了多少客户?现在的要求是假设在 2018 年 11 月
这个问题已经有答案了: Is Java "pass-by-reference" or "pass-by-value"? (91 个回答) 已关闭 8 年前。 我对 ArrayList Collecti
我意识到下面的代码是正确的 Integer.MIN_VALUE == -Integer.MIN_VALUE == Math.abs(Integer.MIN_VALUE) 这是因为当我们取反-21474
我有以下类 AccountWebappGridRow,它扩展了 AccountGridRow: public class AccountWebappGridRow extends AccountGri
我正在学习 Haskell 并看到了函数组合。 尝试复合 map和 foldl mapd = (map.foldl) 比 test = (mapd (\x y -> x + y ) [1,2,3,4]
我有两个相同大小的数组和两个方法。 public class Client { private static int[] ints; private static final int
我喜欢 Java 8 中的 Streams 概念。现在我想借助 Java Streams 将 Java 中的 Map 转换为排序列表。我只想显示列表而不将其存储在任何地方。我希望在结果列表中有这个输出
我有一个数据库表,其中包含电视节目类型列表和关联的 ARGB 颜色值,用于在显示电视指南时突出显示 Android ListView 中的电视节目。流派表看起来像这样... id genre
我有一个 Integer 类,它应该模拟一个整数 mod n。因此,它具有如下构造函数: Integer::Integer(int x) : m(x), n(0) { } Integer::I
我是一名优秀的程序员,十分优秀!