2012-03-03 41 views
0

这是numberOfLeadingZeros(长ⅰ)在Long.java:我不认为long.java中的numberOfLeadingZeros(long i)是基于floor(log2(x))= 63 - numberOfLeadingZeros(x)!

public static int numberOfLeadingZeros(long i) { 
     // HD, Figure 5-6 
     if (i == 0) 
      return 64; 
     int n = 1; 
     int x = (int)(i >>> 32); 
     if (x == 0) { n += 32; x = (int)i; } 
     if (x >>> 16 == 0) { n += 16; x <<= 16; } 
     if (x >>> 24 == 0) { n += 8; x <<= 8; } 
     if (x >>> 28 == 0) { n += 4; x <<= 4; } 
     if (x >>> 30 == 0) { n += 2; x <<= 2; } 
     n -= x >>> 31; 
     return n; 
} 

和作者说,它是基于地板(LOG2(X))= 63 - numberOfLeadingZeros(x)或小区(LOG2(x)的)= 64 - numberOfLeadingZeros(x - 1),是真的吗?或者我可能很愚蠢,无法理解?

有人能解释给我吗?谢谢!

+0

*“或者我是如此愚蠢,无法理解?”* - 我们无法回答这个问题:-)。 – 2012-03-03 04:30:22

+0

:>。有时我很蠢! – liuxiaori 2012-03-03 05:12:36

回答

2

的数字在许多数为floor(log(num)) + 1(与日志中的正确位置。)如果总的数字空间为x,则前导零的数目是

x - (floor(log(num)) + 1) = 
(x - 1) - floor(log(num)) 

所以你的情况,与64个总位数和二进制

leadingZeros(num) = 63 - floor(log_2(num)) 

编辑号码:

>>>是未在Java中是带符号的右移运算符,而<<是左移。 n >>> 32将向右移动32位n,同时用0填充空白区域。

所以算法的工作原理如下:

0000000000000000000000000000000000000000000001011010100000101011 
  1. 移位i 32位到右侧,x仅包含高32位。

    00000000000000000000000000000000

  2. 若(a),这是0,我们知道的高32位是0,以便添加32至前导零计数和集中在低32位。 (b)否则,这是非零的,因此该数字少于32个前导零。集中在高32位。

  3. 移位x向右16位。

    0000000000000101

    通过相同的方法:(1)如果是0,加16前导零计数和集中下一个最低的16位(通过把它们留到领域,我们正在努力(b)如果它不为零,那么我们有少于16个前导零来添加。

  4. 重复下一个字节,然后是下4位,2位和最后一位。

+0

是的,我知道这一点。是含糊不清的me.is日志牵连whit >>> in Java?为什么使用'n'和最后一行的含义是什么n - = x >>> 31 – liuxiaori 2012-03-03 05:11:41

0

是的,只要您将x视为无符号数字即可。

+0

是java的无符号数字吗? – liuxiaori 2012-03-03 05:16:11

+0

@liuxiaori - 是的,但你可以*解释*为无符号的有符号数字。 – 2012-03-03 05:38:21

+0

哦,我的意思是有一个单一类型的无符号数.haha – liuxiaori 2012-03-03 05:55:58