我有一个2的幂的整数输入(1、2、4、8等)。我希望函数不使用log()返回位位置。例如,对于上述输入,对于C#,将分别返回{0,1,2,3}。另外,如果可以在SQL中完成。
谢谢!
我发现执行此操作最快的代码来自Bit Twiddling
Hacks网站。具体而言,基于DeBruijn序列的查找。参见http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
我测试了一个朴素的方法,一个基于开关的方法以及两个Bit Twiddling
Hacks方法:DeBruijn序列,另一个表示“如果您知道自己的价值是2的幂”。
我将所有这些与3200万的2的幂进行比较。也就是说,形式为2 ^ N的整数,其中N在0..30的范围内。2 ^
31的值是负数,这会使幼稚的方法陷入无限循环。
我在发布模式下使用Visual Studio 2010编译了代码,然后在没有调试器(即Ctrl +
F5)的情况下运行了该代码。在我的系统上,数十次运行的平均值是:
显然,DeBruijn序列方法比任何其他方法都快得多。另一个Bithack方法在这里较差,因为从C到C#的转换会导致效率低下。例如,C语句int r = (v & b[0]) != 0;
最终需要if
在C#中使用或三元运算符(即?:)。
这是代码。
class Program
{
const int Million = 1000 * 1000;
static readonly int NumValues = 32 * Million;
static void Main(string[] args)
{
// Construct a table of integers.
// These are random powers of two.
// That is 2^N, where N is in the range 0..31.
Console.WriteLine("Constructing table");
int[] values = new int[NumValues];
Random rnd = new Random();
for (int i = 0; i < NumValues; ++i)
{
int pow = rnd.Next(31);
values[i] = 1 << pow;
}
// Run each one once to make sure it's JITted
GetLog2_Bithack(values[0]);
GetLog2_DeBruijn(values[0]);
GetLog2_Switch(values[0]);
GetLog2_Naive(values[0]);
Stopwatch sw = new Stopwatch();
Console.Write("GetLog2_Naive ... ");
sw.Restart();
for (int i = 0; i < NumValues; ++i)
{
GetLog2_Naive(values[i]);
}
sw.Stop();
Console.WriteLine("{0:N0} ms", sw.ElapsedMilliseconds);
Console.Write("GetLog2_Switch ... ");
sw.Restart();
for (int i = 0; i < NumValues; ++i)
{
GetLog2_Switch(values[i]);
}
sw.Stop();
Console.WriteLine("{0:N0} ms", sw.ElapsedMilliseconds);
Console.Write("GetLog2_Bithack ... ");
sw.Restart();
for (int i = 0; i < NumValues; ++i)
{
GetLog2_Bithack(values[i]);
}
Console.WriteLine("{0:N0} ms", sw.ElapsedMilliseconds);
Console.Write("GetLog2_DeBruijn ... ");
sw.Restart();
for (int i = 0; i < NumValues; ++i)
{
GetLog2_DeBruijn(values[i]);
}
sw.Stop();
Console.WriteLine("{0:N0} ms", sw.ElapsedMilliseconds);
Console.ReadLine();
}
static int GetLog2_Naive(int v)
{
int r = 0;
while ((v = v >> 1) != 0)
{
++r;
}
return r;
}
static readonly int[] MultiplyDeBruijnBitPosition2 = new int[32]
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
static int GetLog2_DeBruijn(int v)
{
return MultiplyDeBruijnBitPosition2[(uint)(v * 0x077CB531U) >> 27];
}
static readonly uint[] b = new uint[] { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000};
static int GetLog2_Bithack(int v)
{
int r = (v & b[0]) == 0 ? 0 : 1;
int x = 1 << 4;
for (int i = 4; i > 0; i--) // unroll for speed...
{
if ((v & b[i]) != 0)
r |= x;
x >>= 1;
}
return r;
}
static int GetLog2_Switch(int v)
{
switch (v)
{
case 0x00000001: return 0;
case 0x00000002: return 1;
case 0x00000004: return 2;
case 0x00000008: return 3;
case 0x00000010: return 4;
case 0x00000020: return 5;
case 0x00000040: return 6;
case 0x00000080: return 7;
case 0x00000100: return 8;
case 0x00000200: return 9;
case 0x00000400: return 10;
case 0x00000800: return 11;
case 0x00001000: return 12;
case 0x00002000: return 13;
case 0x00004000: return 14;
case 0x00008000: return 15;
case 0x00010000: return 16;
case 0x00020000: return 17;
case 0x00040000: return 18;
case 0x00080000: return 19;
case 0x00100000: return 20;
case 0x00200000: return 21;
case 0x00400000: return 22;
case 0x00800000: return 23;
case 0x01000000: return 24;
case 0x02000000: return 25;
case 0x04000000: return 26;
case 0x08000000: return 27;
case 0x10000000: return 28;
case 0x20000000: return 29;
case 0x40000000: return 30;
case int.MinValue: return 31;
default:
return -1;
}
}
}
如果我通过展开循环并使用常量而不是数组查找来优化Bithack代码,则其时间与switch语句方法的时间相同。
static int GetLog2_Bithack(int v)
{
int r = ((v & 0xAAAAAAAA) != 0) ? 1 : 0;
if ((v & 0xFFFF0000) != 0) r |= (1 << 4);
if ((v & 0xFF00FF00) != 0) r |= (1 << 3);
if ((v & 0xF0F0F0F0) != 0) r |= (1 << 2);
if ((v & 0xCCCCCCCC) != 0) r |= (1 << 1);
return r;
}
我的老师想让我通过迭代找到用户10个输入的中位数。 这就是我使用迭代来查找总和,奇数数,最大值和质数数的方式。但我一直坚持要找到中位数。
我已经用一些视频(比如10个)实现了一个回收器视图。单击任何项目都会打开一个上,其中包含所有项目显示单击的一个(来自)。之后,用户只能从那里滚动到其他项目。一切正常。 唯一的问题是当recyclerview项单击viewpager2打开的位置时滚动。 无论何时选择任何项目(第10个)。viewpager首先打开,然后滚动到(第10)个位置。我想不滚动直接打开viewpager2的第10个位置。任何
我有一个具有两个属性的dynamoDB表: A: 主分区键 B: 主排序键 我想使用属性B查询这个表,因为我不知道A的值。可以这样做吗? 是否可以将B设为GSI(全局二级索引),如何使用B查询表,因为B已经是排序键。
问题内容: 是否可以在不使用GPS或互联网的情况下获取用户的当前位置?我的意思是在移动网络提供商的帮助下。 问题答案: 您要做的是使用而不是获取职位将解决在GSM或WiFi,这永远可用。显然,关闭wifi后,将使用GSM。请记住,使用小区网络的精度基本上可以达到500m。 http://developer.android.com/guide/topics/location/obtaining-us
问题内容: 我已经看到了几种通过首先导入来查找模块路径的方法。有没有一种方法,而无需导入模块? 问题答案: 使用pkgutil模块: 使用imp模块: 注意:使用imp模块,您 无法 做类似的事情
我想复制这家伙做的但不使用画布。我想有一个div在我的页面的中心,并简单地增加宽度/高度/边界半径10px每秒。这工作得很好,但是由于某种原因,div越大,它向右下方移动的越多。圆圈不是静止不动的,它的中心位置随着它变大而改变。如何在不改变位置的情况下更改div的宽度/高度? main.css index.html APP咖啡