繁体   English   中英

C# 反转 integer 的位

[英]C# reversing the bits of an integer

我知道这已被多次询问类似的差异,但我在 C#(Unity3D) 中的按位运算 output 遇到了麻烦。

我正在尝试进行位反转置换,即为了在Cooley-Tukey FFT 算法中使用的目的,获取整数(或无符号整数,两者之一)的位反转顺序。 因此,如果我有 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# 中执行相同的 function,就像在其他语言(如 C)中一样,对吗? 那么,我错过了一步吗?

当前正在使用扭转整个整数位(对于即32位的算法int和一个64位long ),而你真的想要的是扭转只有第一 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定义如下

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 )填充符号位的情况。

如果要实现给定位长的功能(如果您知道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;
}
    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;

由于 glsl 具有bitfieldReverse()操作,因此bitfieldReverse()正在反转所有 32 位。

在 FFT 的情况下,只需要反转最右边的log2(N)位。 因此,可以引入两个额外的 int uniform shiftBitsbitfieldMask来完成正确的reverse_bits() function。

uniform int shiftBits; // 32-log2(N)
uniform int bitfieldMask; // 1<<log2(N) - 1;

int reverse_bits( int y )
{
    return (bitfieldReverse(y)>>shiftBits) & bitfieldMask;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM