将整数转换为位表示形式

14

如何将整数转换为其位表示形式。我想要输入一个整数并返回一个向量,其中包含整数的二进制表示中的1和0。

我自己试着做这个任务遇到了很大的困难,所以我想问一下是否有内置的库函数可以帮助做到这一点。


2
我想你的意思是比特表示。 - fbrereto
既然整数是固定大小的,为什么不只使用一个简单的数组呢? - Jon Cage
@bobber205:你可能需要编辑你的问题以避免进一步的混淆。 - Paul R
如果您可以构建一个位集,它已经有一个to_string方法,可以创建一个0和1序列。不幸的是,即使它们有to_ulong,也没有from_ulong方法。 - Mark B
6个回答

18

不能处理负数。

vector<int> convert(int x) {
  vector<int> ret;
  while(x) {
    if (x&1)
      ret.push_back(1);
    else
      ret.push_back(0);
    x>>=1;  
  }
  reverse(ret.begin(),ret.end());
  return ret;
}

非常感谢!我现在可以按照我最初的意图实现算法了。 :D - bobber205
3
或者 do ret.push_back( x & 1 ) while ( x >>= 1 ); — 这个版本会在输入为 0 时返回一个零比特。 - Potatoswatter

6

虽然使用一行代码解决这个问题并不太难,但实际上有一个标准库的解决方案。

#include <bitset>
#include <algorithm>

std::vector< int > get_bits( unsigned long x ) {
    std::string chars( std::bitset< sizeof(long) * CHAR_BIT >( x )
        .to_string< char, std::char_traits<char>, std::allocator<char> >() );
    std::transform( chars.begin(), chars.end(),
        std::bind2nd( std::minus<char>(), '0' ) );
    return std::vector< int >( chars.begin(), chars.end() );
}

C++0x甚至使它更容易!

#include <bitset>

std::vector< int > get_bits( unsigned long x ) {
    std::string chars( std::bitset< sizeof(long) * CHAR_BIT >( x )
        .to_string( char(0), char(1) ) );
    return std::vector< int >( chars.begin(), chars.end() );
}

这是图书馆中比较奇怪的一个角落。也许他们真正想表达的是序列化。

cout << bitset< 8 >( x ) << endl; // print 8 low-order bits of x

3
DCP的答案有所改动。对于t的负值,其行为是实现定义的。它提供所有位数,包括前导零。使用std::vector<bool>的标准注意事项和它不是一个合适的容器相关。
#include <vector>    //for std::vector
#include <algorithm> //for std::reverse
#include <climits>   //for CHAR_BIT

template<typename T>
std::vector<bool> convert(T t) {
  std::vector<bool> ret;
  for(unsigned int i = 0; i < sizeof(T) * CHAR_BIT; ++i, t >>= 1)
    ret.push_back(t & 1);
  std::reverse(ret.begin(), ret.end());
  return ret;
}

以下是可能适用于浮点值以及其他POD类型的版本。 我并没有真正测试过它。 它对负数的处理效果可能更好,也可能更差。 我没有仔细思考过。

template<typename T>
std::vector<bool> convert(T t) {
  union {
    T obj;
    unsigned char bytes[sizeof(T)];
  } uT;
  uT.obj = t;

  std::vector<bool> ret;
  for(int i = sizeof(T)-1; i >= 0; --i) 
    for(unsigned int j = 0; j < CHAR_BIT; ++j, uT.bytes[i] >>= 1)
      ret.push_back(uT.bytes[i] & 1);
  std::reverse(ret.begin(), ret.end());
  return ret;
}

字节序问题可能会在第二个中出现,是吧?噢,没关系。 - Dennis Zickefoose

2

这里是一个可以处理负数的版本:

string get_bits(unsigned int x)
{
  string ret;
  for (unsigned int mask=0x80000000; mask; mask>>=1) {
    ret += (x & mask) ? "1" : "0";
  }
  return ret;
}

这个字符串当然可以被向量替换或用于位值索引。


1
返回字符串而不是向量,但可以很容易地更改。
template<typename T>
std::string get_bits(T value) {
    int size = sizeof(value) * CHAR_BIT;
    std::string ret;
    ret.reserve(size);
    for (int i = size-1; i >= 0; --i)
        ret += (value & (1 << i)) == 0 ? '0' : '1';
    return ret;
}

0

世界上最糟糕的整数转换为位和字节的转换器:

#include <algorithm>
#include <functional>
#include <iterator>
#include <stdlib.h>

class zero_ascii_iterator: public std::iterator<std::input_iterator_tag, char>
{
public:
    zero_ascii_iterator &operator++()
    {
        return *this;
    }

    char operator *() const
    {
        return '0';
    }
};


char bits[33];

_itoa(value, bits, 2);
std::transform(
    bits, 
    bits + strlen(bits), 
    zero_ascii_iterator(), 
    bits, 
    std::minus<char>());

3
哇,我想知道为什么Perl被认为是难以理解的 =) - maerics
绝对值得在codinghorror上拥有一个独特的空间。 - jweyrich
这是一个来自现实生活的例子吗? - Potatoswatter
希望不会。我想写这段代码而不使用boost::bind(...)。 - MSN

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