我知道有很多次类似的差异,但我在C#(Unity3D)中按位运算的输出有问题。
我正在尝试bit-reversal permutation,也就是说,在Cooley-Tukey FFT algorithm中使用整数的位反转顺序(或者unsigned int,任一个)。所以,如果我有0,1,2,3 - 我想最终得到0,2,1,3,如果我有0,1,2,3,4,5,6,7 - 我应该得到0, 4,2,6,1,5,3,7。
我尝试过在线发现的一些位反转算法,例如:
public uint ReverseBits(uint n)
{
n = (n >> 1) & 0x55555555 | (n << 1) & 0xaaaaaaaa;
n = (n >> 2) & 0x33333333 | (n << 2) & 0xcccccccc;
n = (n >> 4) & 0x0f0f0f0f | (n << 4) & 0xf0f0f0f0;
n = (n >> 8) & 0x00ff00ff | (n << 8) & 0xff00ff00;
n = (n >> 16) & 0x0000ffff | (n << 16) & 0xffff0000;
return n;
}
我会像这样使用它:
uint x = 1;
x = ReverseBits(x); //this results in x = 2147483648;
我想尝试另一种算法,所以我找到了这个算法,正如指出的那样反转了字节:
public uint ReverseBytes(uint value)
{
return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 |
(value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24;
}
我得到完全相同的号码x = 2147483648
。像>>
这样的按位运算符在C#中执行与在其他语言(如C)中相同的功能,对吗?那么,我错过了一步吗?
答案 0 :(得分:3)
您当前使用的算法会反转整数中的位(即int
为32位,long
为64位),而您真正使用的是想要只反转第一个 k
位(其中n = 2^k
用于位反转排列)。
一个简单的解决方案是使用字符串:
int x = 6;
int k = 3;
// Binary representation of x of length k
string binaryString = Convert.ToString(x, 2).PadLeft(k, '0');
int reversed = Convert.ToInt32(Reverse(binaryString), 2);
其中Reverse
is defined as follows:
public static string Reverse( string s )
{
char[] charArray = s.ToCharArray();
Array.Reverse( charArray );
return new string( charArray );
}
或者,如果您不想使用字符串,您可以坚持使用按位运算符解决方案:
int x = 6;
int k = 3;
int reversed = 0;
for(int i = 0; i < k; i++) {
// If the ith bit of x is toggled, toggle the ith bit from the right of reversed
reversed |= (x & (1 << i)) != 0 ? 1 << (k - 1 - i) : 0;
}
您甚至可以以可读性为代价删除三元运算符:
reversed |= (((x & (1 << i)) >> i) & 1) << (k - 1 - i);
& 1
补偿了正确的算术移位(>> i
)填充符号位的情况。
答案 1 :(得分:1)
如果要实现给定位长度的函数(如果您知道DFT具有给定长度,如64),那么您可以对各种常量进行硬编码并编写适合该位长度的函数,例如:
public static int Reverse6Bits(int n)
{
n = (n >> 1) & 0x55 | (n << 1) & 0xaa;
n = (n >> 2) & 0x33 | (n << 2) & 0xcc;
n = (n >> 6) & 0x03 | (n << 2) & 0x3c;
return n;
}
如果我有0,1,2,3,4,5,6,7 - 我应该得到0,4,2,6,1,5,3,7
您可以使用常量作为查找表来反转3位:
public static int Reverse3Bits(int n)
{
return (0x73516240 >> (n << 2)) & 7;
}
答案 2 :(得分:0)
uint ret=n;
ret = ret >> 16 | ret<<16;
ret = (ret & 0xff00ff00) >> 8 | (ret & 0x00ff00ff) << 8;
ret = (ret & 0xf0f0f0f0) >> 4 | (ret & 0x0f0f0f0f) << 4;
ret = (ret & 0xcccccccc) >> 2 | (ret & 0x33333333) << 2;
ret = (ret & 0xaaaaaaaa) >> 1 | (ret & 0x55555555) << 1;
return ret;