将12位整数转换为16位或32位

6

我正在从字节数组中读取一个12位的整数。这个数字可以是负数,但我不知道如何将其转换为可用的int16/int32类型变量。我有一种感觉需要使用位移或其他按位操作,但到目前为止我一直失败了。请问有人能指点我正确的方向吗?

var x = 0xFFF;

这应该输出为-1,但是C#自然地将其强制转换为int32并输出为4095。如果需要将其强制转换为int16或int32,该如何保留负数值呢?

3个回答

13

32位:

x = (x >> 11) == 0 ? x : -1 ^ 0xFFF | x;

非常好,非常感谢!能否解释一下这里发生了什么?我知道 >> ^ | 的作用,但还没有完全理解。 - Clarke76
2
基本上是向右移位,直到只剩下符号位。如果它是零,那么我们只返回原始值。如果它是1,那么我们取-1(0xFFFFFFFF),关闭低12位(xor),然后与原始值进行or运算以打开其中的位。结果基本上就是打开32位值的高20位。 - Andrew Cooper
是的...我最终把所有东西都写在纸上,看到了确切发生了什么。那真的很有帮助。我忘记了最后一部分会被用作负数标志。之后就很容易跟进了。再次感谢。 - Clarke76

8

假设x已经是包含12位值的有符号短整型,无需条件地进行符号扩展:

x = (x << 4) >> 4;

括号仅用于理解正在发生的事情。位移运算符与其他算术和逻辑运算符一样是左结合的。这个方法之所以起作用,是因为>>对于有符号类型来说是算术右移。这意味着,在最高有效位上,它不是将零移入,而是将MSB重复多次。

n位到m位的常规符号扩展如下:

x = (x << (m - n)) >> (m - n);

显而易见的原因是,sbytem 会被限制为8,short 为16,int 为32,long 为64。再次说明,括号仅仅是美观上的需要。减法的优先级高于位移操作。


1
检测符号位并进行扩展。对于16位:
x = ( x & 0x800 ? x | 0xf000 : x );

你可以在这里用OR替换XOR。 - Der_Meister

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接