这个问题在没有特定语言的情况下更为通用。我对跨语言解决这个问题更感兴趣。我发现的每个答案都引用了getInt32
之类的内置方法来从字节数组中提取整数。
我有一个字节数组,其中包含有符号整数的big-endian表示形式。
1 -> [0, 0, 0, 1]
-1 -> [255, 255, 255, 255]
-65535 -> [255, 255, 0, 1]
获得阳性病例的值很容易:
arr[3] | arr[2] << 8 | arr[1] << 16 | arr[0] << 24
我想弄清楚的是更一般的情况。我一直在阅读有关2s补码的信息,这使我进入了Wikipedia的python函数:
def twos_complement(input_value, num_bits):
'''Calculates a two's complement integer from the given input value's bits'''
mask = 2**(num_bits - 1) - 1
return -(input_value & mask) + (input_value & ~mask)
这反过来导致我产生此功能:
# Note that the mask from the wiki function has an additional - 1
mask = 2**(32 - 1)
def arr_to_int(arr):
uint_val = arr[3] | arr[2] << 8 | arr[1] << 16 | arr[0] << 24
if (determine_if_negative(uint_val)):
return -(uint_val & mask) + (uint_val & ~mask)
else:
return uint_val
为了使我的功能正常工作,我需要填写determine_if_negative
(我应该屏蔽带符号的位并检查它是否为1)。但是是否有标准的公式可以处理?我发现的一件事是,在某些语言(例如Go)中,移位可能会使int值溢出。
这很难搜索,因为我得到了一千个解释大尾数法和小尾数法之间的区别的结果,或者解释了二进制补码的结果,还有更多给出使用标准库的示例,但我还没有看到完整的例子。位函数的公式。
是否有C或类似语言的规范示例,仅使用数组访问和按位函数(即,没有memcpy或指针转换或棘手的东西)来转换char数组
答案 0 :(得分:0)
按位方法仅适用于无符号值,因此您将需要构建无符号整数,然后转换为有符号。代码可能是:
int32_t val( uint8_t *s )
{
uint32_t x = ((uint32_t)s[0] << 24) + ((uint32_t)s[1] << 16) + ((uint32_t)s[2] << 8) + s[3];
return x;
}
请注意,这假设您使用的是2的补码系统,该系统还将unsigned-> signed转换定义为表示形式不变。如果您也想支持其他系统,那就更复杂了。
必须进行强制转换,以便在正确的宽度上执行移位。
答案 1 :(得分:0)
即使c对此也可能太高了。毕竟,int的确切表示形式取决于机器。除此之外,并非所有系统上的所有整数类型都是2s补码。
当提到字节数组并将其转换为整数时,必须指定该字节数组所隐含的格式。
如果您假设2s补码和小尾数(例如intel / amd)。然后最后一个字节包含符号。
为简单起见,让我们以4位2s补码整数开始,然后是字节字节,然后是2字节整数,然后是4。
BIN SIGNED_DEC UNSIGNED_DEC
000 0 0
001 1 1
010 2 2
100 -4(oops) 4
101 -3 5
110 -1 6
111 -1 7
---
123
让每个位为b3,b2,b1,其中b1是最高有效位(和符号) 那么公式将是:
b3*2^2+b2*2^1-b1*4
对于一个字节,我们有4位,其公式如下所示:
b4*2^3 + b3*2^2+b2*2^1-b1*2^3
对于2个字节,它是相同的,但我们必须将最高有效字节乘以256,负值将为256 ^ 2或2 ^ 16。
/**
* returns calculated value of 2s complement bit string.
* expects string of bits 0or1. if a chanracter is not 1 it is considered 0.
*
*/
public static long twosComplementFromBitArray(String input) {
if(input.length()<2) throw new RuntimeException("intput too short ");
int sign=input.charAt(0)=='1'?1:0;
long unsignedComplementSum=1;
long unsignedSum=0;
for(int i=1;i<input.length();++i) {
char c=input.charAt(i);
int val=(c=='1')?1:0;
unsignedSum=unsignedSum*2+val;
unsignedComplementSum*=2;
}
return unsignedSum-sign*unsignedComplementSum;
}
public static void main(String[] args) {
System.out.println(twosComplementFromBitArray("000"));
System.out.println(twosComplementFromBitArray("001"));
System.out.println(twosComplementFromBitArray("010"));
System.out.println(twosComplementFromBitArray("011"));
System.out.println(twosComplementFromBitArray("100"));
System.out.println(twosComplementFromBitArray("101"));
System.out.println(twosComplementFromBitArray("110"));
System.out.println(twosComplementFromBitArray("111"));
}
输出:
0
1
2
3
-4
-3
-2
-1