从bitset <n>签名int

时间:2016-03-07 17:17:37

标签: c++ c++11 bitset

如何将长度为N (其中0 < N < 64的给定位集转换为signed int。例如,给定:

std::bitset<13> b("1111111101100");

我想取回值-20,而不是8172.

我的方法:

int t = (static_cast<int>(b.to_ullong()));
if(t > pow(2, 13)/2)
    t -= pow(2, 13);

有没有更通用的方法来解决这个问题?

编辑:此外,bitset实际上是std::bitset<64>,N可以是通过其他方式传递的运行时已知值。

2 个答案:

答案 0 :(得分:1)

我们可以编写一个函数模板来为我们这样做:

c(1, 2, 1, 2)
c(1, 2, 1, 4)
c(1, 2, 3, 2)
c(1, 2, 3, 4)

答案 1 :(得分:0)

也许最好让编译器自己对其进行签名扩展:

struct S { int64_t x:N; } s;
int64_t result = s.x = b.to_ullong();

编译器可能会优化s

它必须是安全的,因为int64_t(如果可用)需要是两个补码。

编辑:当扩展的实际位数仅为已知运行时间时,大多数便携式算法都带有掩码:

// Do this if bits above position N in b may be are not zero to clear those.
int64_t x = b.to_ullong() & ((1ULL << N) - 1);
// Otherwise just 
int64_t x = b.to_ullong();

int64_t const mask = 1ULL << (N - 1);
int64_t result = (x ^ mask) - mask;

具有动态位计数的稍快但不太便携的方法是位移(当架构已经签名算术右移时有效):

int const shift = 64 - N;
int64_t result = ((int64_t)b.to_ullong() << shift) >> shift;