Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.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
C 2次幂的有效计算_C_Performance_Math_Optimization - Fatal编程技术网

C 2次幂的有效计算

C 2次幂的有效计算,c,performance,math,optimization,C,Performance,Math,Optimization,我需要将k计算为2的最小幂,即>=整数值,n(n始终大于0) 目前我正在使用: #define log2(x) log(x)/log(2) #define round(x) (int)(x+0.5) k = round(pow(2,(ceil(log2(n))))); 这是一个性能关键的功能 有没有更有效的计算k的方法?k=1 k = 1 << (int)(ceil(log2(n))); 研究它,看看它是如何工作的,这很有趣。我认为,要确定您看到的解决方案中哪一个最适合您的情况

我需要将
k
计算为2的最小幂,即>=整数值,
n
n
始终大于0)

目前我正在使用:

#define log2(x) log(x)/log(2)
#define round(x) (int)(x+0.5)

k = round(pow(2,(ceil(log2(n)))));
这是一个性能关键的功能

有没有更有效的计算
k
的方法?

k=1
k = 1 << (int)(ceil(log2(n)));
研究它,看看它是如何工作的,这很有趣。我认为,要确定您看到的解决方案中哪一个最适合您的情况,唯一的方法是在文本夹具中使用所有这些解决方案,并对其进行分析,看看哪一个对您的目的最有效

由于没有分支,与其他一些分支相比,这个分支在性能方面可能相当好,但是您应该直接测试它以确保

如果希望二的最小幂大于或等于X,可以使用稍微不同的解决方案:

unsigned
clp2(unsigned x)
{
    x = x -1;
    x = x | (x >> 1);
    x = x | (x >> 2);
    x = x | (x >> 4);
    x = x | (x >> 8);
    x = x | (x >> 16);
    return x + 1;
}
lim=123;
n=1;

而((n=nYes),您可以通过简单地获取所讨论的数字,并使用位移位来确定2的幂来计算它。
右移取数字中的所有位并向右移动,删除最右边(最低有效位)数字。它相当于执行整数除以2。左移一个值会将所有位移到左边,删除从左端移走的位,并将零添加到右端,有效地将该值乘以2。 因此,如果您计算在数字达到零之前需要右移多少次,您已经计算了以2为底的对数的整数部分。然后使用它通过将值1左移多少次来创建结果

  int CalculateK(int val)
  {
      int cnt = 0;
      while(val > 0)
      {
           cnt++;
           val = val >> 1;
      }
      return 1 << cnt;
  }
int-CalculateK(int-val)
{
int-cnt=0;
while(val>0)
{
cnt++;
val=val>>1;
}
返回1
int计算2(int x)的最小覆盖幂
{
int k=1;

而(k
/* altered to: power of 2 which is greater than an integer value */

unsigned clp2(unsigned x) {
   x = x | (x >> 1);
   x = x | (x >> 2);
   x = x | (x >> 4);
   x = x | (x >> 8);
   x = x | (x >>16);
   return x + 1;
}
请记住,您需要添加:

x = x | (x >> 32);


对于64位数字。

如果您使用的是GCC,您可以使用
1注释编辑从'>a integer value'到'>=a integer value',现在每个人都必须再次更改答案。:-)要求使用堆栈溢出的“撤消”按钮…与答案无关,但对于遇到此问题且不太清楚的人来说,值得一提:明智的做法是放弃+0.5和(int)类型,改用floor()或天花()计算中的函数是这样的。当然,对数仍然很慢。这很好,因为“最左边的”1是答案,目标是将所有其他位置为0,这很好。您将需要一个额外的行来表示64位数字。啊,是的,您还需要其他内容,让我来发布。如果您使用
x |=x>>1;…
表单,您可以去掉t他用括号括起来,因为赋值运算符的优先级很低。是的。将最终结果上移或下移2的一次方(取决于实际意图)非常简单。希望Hiett能够将这些信息用于其程序的特定需要。@Hiett因为右移0仍然是0,如果您需要同时满足32位和64位的要求,可以添加额外的行。32位的结果仍然是正确的,只会浪费一些指令此代码不编译,因为
ceil
具有类型
double
,不能与
一起使用。我在示例中添加了对int的强制转换。我不确定为什么n=32的期望结果是64…可能我不理解原始问题。@EricPostChil,它似乎要求2的最小幂大于或等于n。32等于32。但可能我仍然有误解。不管怎样,Randy Howard的答案都更好。@EricPostphil Tnx注意,修复了…(对于lim=0不起作用,但可以使用if()解决)用无分支版本对此进行基准测试,我想你会发现这不是最有效的方法。但是,它会起作用。@RandyHoward我已经这样做了,没有明显的区别(对于我的应用程序)所以我想我会坚持这个答案simpler@Randy:此简单方法非常容易理解,不能移植到64-(128-,…)位机。首先理解它,然后转到无分支版本也很有帮助。无分支版本对于均匀分布的32位整数肯定会更有效,但对于小整数可能会慢一些。此外,我给你的帖子加了“+1”,我的帖子被接受了,这真是一个惊喜。)@alex shesterov你能解释一下将函数移植到64位机器的问题吗?@Hiett:这个答案中的函数适用于16、32、64位的任何系统,没有任何更改;它的复杂性(迭代次数)等于系统位的数量(即16、32、64位或其他)在最坏的情况下-也就是说,它在位数上是线性的。RandyHoward的答案中的函数需要通过添加
x |=x>>32
来移植到64位平台,其复杂度在最坏和最佳情况下都是对数的。我估计RandyHoward的函数在32位系统上平均比这个函数快15%。
  int CalculateK(int val)
  {
      int res = 1;
      while(res <= val) res <<= 1;
      return res ;
  }
int calculate_least_covering_power_of_two(int x)
{
  int k = 1;
  while( k < x ) k = k << 1;
  return k;
}
/* altered to: power of 2 which is greater than an integer value */

unsigned clp2(unsigned x) {
   x = x | (x >> 1);
   x = x | (x >> 2);
   x = x | (x >> 4);
   x = x | (x >> 8);
   x = x | (x >>16);
   return x + 1;
}
x = x | (x >> 32);