Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 如何得到2^k数的lg2_Performance_Bit Manipulation_Micro Optimization_Logarithm_Bitcount - Fatal编程技术网

Performance 如何得到2^k数的lg2

Performance 如何得到2^k数的lg2,performance,bit-manipulation,micro-optimization,logarithm,bitcount,Performance,Bit Manipulation,Micro Optimization,Logarithm,Bitcount,我所知道的一个数字的2底对数是2的幂(2^k)的最佳解决方案是什么。(当然,我只知道值2^k而不知道k本身。) 我想到的一种方法是减去1,然后进行位计数: lg2(n) = bitcount( n - 1 ) = k, iff k is an integer 0b10000 - 1 = 0b01111, bitcount(0b01111) = 4 但是有没有一种更快的方法(不需要缓存)?还有一件事,不涉及比特数大约快将很高兴知道 其中一个应用是: suppose you have bitmas

我所知道的一个数字的2底对数是2的幂(
2^k
)的最佳解决方案是什么。(当然,我只知道值
2^k
而不知道
k
本身。)

我想到的一种方法是减去1,然后进行位计数:

lg2(n) = bitcount( n - 1 ) = k, iff k is an integer
0b10000 - 1 = 0b01111, bitcount(0b01111) = 4
但是有没有一种更快的方法(不需要缓存)?还有一件事,不涉及比特数大约快将很高兴知道

其中一个应用是:

suppose you have bitmask
0b0110111000

and value
0b0101010101

and you are interested of
(value & bitmask) >> number of zeros in front of bitmask
(0b0101010101 & 0b0110111000) >> 3 = 0b100010

this can be done with

using bitcount
value & bitmask >> bitcount((bitmask - 1) xor bitmask) - 1

or using lg2
value & bitmask >> lg2(((bitmask - 1) xor bitmask) + 1 ) - 2

要使它比没有缓存的速度快,它应该比
O(lg(k))
快,其中
k
是存储位的计数。

如果您知道该数字是2的幂,您可以将其向右移动(
),直到它等于0。您右移的次数(减1)是您的
k


编辑:比这更快的是查找表方法(尽管您牺牲了一些空间,但一吨也没有)。请参阅。

如果您不介意处理浮点数,您可以使用
log(x)/log(2)
许多体系结构都有“查找第一个”指令(bsr、clz、bfffo、cntlzw等),这将比位计数方法快得多。

是的。如果您知道所讨论的整数是2的幂,那么在
lg(n)
中有一种不使用位计数的方法

unsigned int x = ...;
static const unsigned int arr[] = {
  // Each element in this array alternates a number of 1s equal to
  // consecutive powers of two with an equal number of 0s.
  0xAAAAAAAA, // 0b10101010..         // one 1, then one 0, ...
  0xCCCCCCCC, // 0b11001100..         // two 1s, then two 0s, ...
  0xF0F0F0F0, // 0b11110000..         // four 1s, then four 0s, ...
  0xFF00FF00, // 0b1111111100000000.. // [The sequence continues.]
  0xFFFF0000
}

register unsigned int reg = (x & arr[0]) != 0;
reg |= ((x & arr[4]) != 0) << 4;
reg |= ((x & arr[3]) != 0) << 3;
reg |= ((x & arr[2]) != 0) << 2;
reg |= ((x & arr[1]) != 0) << 1;

// reg now has the value of lg(x).

我们看到,
reg
的最终值是2^0+2^1+2^3,实际上是11。

您必须设置k=#移位-1;它将比bitcount方法慢。您可以在O(lg(k))中进行位计数,这种移位在最坏的情况下是O(k)。(k是存储位的计数)@egon-我能看到的唯一改进lgk的是查找表方法。回答更新。@danben-是的,感觉就像。。。也许有人对如何改进它有很好的想法。它认为,利用数字是2的幂这一事实,它可能会变得更快。它只有
k
个状态,而且不是很多。实际上,我在文章中找到了解决方案。如果值是2的幂,则方法3,4有版本。方法3的版本比使用bitcount快。可能是最快的方法…)如果您没有访问汇编指令的权限,这是最好的方法,但我会去掉数组,直接使用常量。@x4u:这更多是为了说明/教育目的,而不是为了显示优化的代码。但是,我同意。最好的非汇编方法,尽管您可以使用常量,而不是使用array
arr
。这可能会节省几个周期。在大多数CPU上,这将是数百个时钟周期。如果有clz或类似的指令,可以在一个周期内完成。
// x = 2048
//   = 1000 0000 0000

register unsigned int reg = (x & arr[0]) != 0;
// reg =       1000 0000 0000
         & ... 1010 1010 1010
       =       1000 0000 0000 != 0
// reg = 0x1 (1)        // <-- Matched! Add 2^0 to reg.

reg |= ((x & arr[4]) != 0) << 4;
// reg =     0x .. 0800
           & 0x .. 0000
       =              0 != 0
// reg = reg | (0 << 4) // <--- No match.
// reg = 0x1 | 0
// reg remains 0x1.

reg |= ((x & arr[3]) != 0) << 3;
// reg =     0x .. 0800
           & 0x .. FF00
       =            800 != 0
// reg = reg | (1 << 3) // <--- Matched! Add 2^3 to reg.
// reg = 0x1 | 0x8
// reg is now 0x9.         

reg |= ((x & arr[2]) != 0) << 2;
// reg =     0x .. 0800
           & 0x .. F0F0
       =              0 != 0
// reg = reg | (0 << 2) // <--- No match.
// reg = 0x9 | 0
// reg remains 0x9.        

reg |= ((x & arr[1]) != 0) << 1;
// reg =     0x .. 0800
           & 0x .. CCCC
       =            800 != 0
// reg = reg | (1 << 1) // <--- Matched! Add 2^1 to reg.
// reg = 0x9 | 0x2
// reg is now 0xb (11).