C++ 连接boost::dynamic_位集或std::位集

C++ 连接boost::dynamic_位集或std::位集,c++,boost,std,bitset,C++,Boost,Std,Bitset,连接2个位集的最佳方法是什么 例如,我有 boost::dynamic_bitset<> test1( std::string("1111") ); boost::dynamic_bitset<> test2( std::string("00") ); 解决方案应使用boost::dynamic_位集。如果这个解决方案能与std::bitset一起使用,那就太好了。在连接位时,应该关注性能 更新: 我比较了这两种方法(我和Neil的stringmethod和messen

连接2个位集的最佳方法是什么

例如,我有

boost::dynamic_bitset<> test1( std::string("1111") );
boost::dynamic_bitset<> test2( std::string("00") );
解决方案应使用boost::dynamic_位集。如果这个解决方案能与std::bitset一起使用,那就太好了。在连接位时,应该关注性能

更新: 我比较了这两种方法(我和Neil的stringmethod和messenger的shiftmethod),stringmethod的速度要快得多(factor 10++)。代码如下:


我希望Pastebin可以发布长代码列表。如果有更好的方法,请与我联系。

对于入门,我将自己添加一个可能的解决方案。下面的代码可以使用std::string构造位集,并从位集生成std::string

#include <sstream>  // for std::ostringstream
#include <boost/dynamic_bitset.hpp>

boost::dynamic_bitset<> test1( std::string("1111") );
boost::dynamic_bitset<> test2( std::string("00") );

std::ostringstream bitsetConcat;
bitsetConcat << test1 << test2;
boost::dynamic_bitset<> test3( bitsetConcat.str() );

std::cout << test3 << std::endl;
#包含//用于std::ostringstream
#包括
boost::dynamic_位集test1(std::string(“1111”);
boost::dynamic_位集test2(std::string(“00”);
std::ostringstream bitsetConcat;

bitsetConcat对于标准位集,类似于:

#include <bitset>
#include <string>
#include <iostream>
using namespace std;

template <size_t N1, size_t N2 >
bitset <N1 + N2> concat( const bitset <N1> & b1, const bitset <N2> & b2 ) {
    string s1 = b1.to_string();
    string s2 = b2.to_string();
    return bitset <N1 + N2>( s1 + s2 );
}

int main() {
    bitset <4> a( string("1010") );
    bitset <2> b( string("11") );
    cout << concat( a, b ) << endl;
}
#包括
#包括
#包括
使用名称空间std;
模板
位集concat(常量位集&b1、常量位集&b2){
字符串s1=b1。到_字符串();
字符串s2=b2.to_string();
返回位集(s1+s2);
}
int main(){
位集a(字符串(“1010”);
位集b(字符串(“11”);

cout这里有一个解决方案。不确定它是否编译

typedef boost::dynamic_bitset<> Bits;

Bits Concatenate(const Bits& first, const Bits& second)
{
    Bits value(first);

    //Increase the size of the bit buffer to fit the data being placed in it
    value.resize(first.size() + second.size());
    value <<= second.size();
    value |= second;
    return value;
}
typedef boost::动态位集位;
位串联(常量位和第一位,常量位和第二位)
{
位值(第一);
//增加位缓冲区的大小以适合放置在其中的数据
value.resize(first.size()+second.size());

value我已经测试了几种解决方案,似乎:

  • 一个好的“for循环”是最快的
  • 位集比动态位集快得多(不足为奇),如果不需要内存分配,开销会更低,但仍然存在
  • 这似乎很明显,但是,直接将一个位集附加到另一个位集而不创建新的位集速度更快。如果需要保持第一个位集不变(也很明显),则此解决方案不适用
  • 这3种解决方案不会产生相同的结果,您必须根据需要进行一些调整(见下文)
以下是我的测试代码:

#include <iostream>
#include <bitset>
#include <boost/dynamic_bitset/dynamic_bitset.hpp>
#include "scul/PreciseTimer.h"

boost::dynamic_bitset<> concatOperatorsDyn( const boost::dynamic_bitset<>& bs1,const boost::dynamic_bitset<>& bs2)
{
    boost::dynamic_bitset<> bs1Copy(bs1);
    boost::dynamic_bitset<> bs2Copy(bs2);
    size_t totalSize=bs1.size()+bs2.size();
    bs1Copy.resize(totalSize);
    bs2Copy.resize(totalSize);
    bs1Copy<<=bs2.size();
    bs1Copy|=bs2Copy;
    return bs1Copy;
}

template<size_t sRes,size_t s1,size_t s2>
std::bitset<sRes> concatString( const std::bitset<s1>& bs1,const std::bitset<s2>& bs2)
{
    std::string s1=bs1.to_string<char,std::char_traits<char>,std::allocator<char> >();
    std::string s2=bs2.to_string<char,std::char_traits<char>,std::allocator<char> >();

    std::bitset<sRes> res(s1+s2);
    return res;
}

template<size_t sRes,size_t s1,size_t s2>
std::bitset<sRes> concatLoop( const std::bitset<s1>& bs1,const std::bitset<s2>& bs2)
{
    std::bitset<sRes> res;
    for(size_t i=0;i<s1;i++)
        res[i]=bs1[i];

    for(size_t i=0;i<s2;i++)
        res[i+s1]=bs2[i];
    return res;
}
boost::dynamic_bitset<> concatLoopDyn( const boost::dynamic_bitset<>& bs1,const boost::dynamic_bitset<>& bs2)
{
boost::dynamic_bitset<> res(bs1);
res.resize(bs1.size()+bs2.size());
    size_t bs1Size=bs1.size();
    size_t bs2Size=bs2.size();

    for(size_t i=0;i<bs2.size();i++)
        res[i+bs1Size]=bs2[i];
    return res;
}
boost::dynamic_bitset<> concatStringDyn( const boost::dynamic_bitset<>& bs1,const boost::dynamic_bitset<>& bs2)
{
    std::string s1;
    std::string s2;
    to_string(bs1,s1);
    to_string(bs2,s2);

    boost::dynamic_bitset<> res(s1+s2);
    return res;
}


template<size_t s1,size_t s2>
void injectLoop( std::bitset<s1>& bs1,const std::bitset<s2>& bs2,int start=s1-s2)
{
    for(size_t i=0;i<s2;i++)
        bs1[i+start]=bs2[i];
}


void injectLoopDyn( boost::dynamic_bitset<>& bs1,const boost::dynamic_bitset<>& bs2,int start)
{
    for(size_t i=0;i<bs2.size();i++)
        bs1[i+start]=bs2[i];
}

void testBitstream()
{
    const std::bitset<20> bs1(std::string("11111111110000000000"));
    std::bitset<30> bs1Bis(std::string("11111111110000000000"));
    const std::bitset<10> bs2(std::string("0000011111"));
    std::bitset<30> bs3;


    const boost::dynamic_bitset<> bs1D(std::string("11111111110000000000"));
    boost::dynamic_bitset<> bs1DBis(std::string("11111111110000000000"));
    bs1DBis.resize(30);
    const boost::dynamic_bitset<> bs2D(std::string("0000011111"));
    boost::dynamic_bitset<> bs3D;

    scul::PreciseTimer t;
    double d=0.;

    int nbIter=100;

    std::cout<<"Bitset concat with strings"<<std::endl;
    t.start();
    for(int i=0;i<nbIter;++i)
        bs3=concatString<30,20,10>(bs1,bs2);
    d=t.stop();
    std::cout<<bs3.to_string<char,std::char_traits<char>,std::allocator<char> >()<<std::endl;
    std::cout<<"duration="<<d<<std::endl<<std::endl;;


    std::cout<<"Bitset concat with loop"<<std::endl;
    t.start();
    for(int i=0;i<nbIter;++i)
        bs3=concatLoop<30,20,10>(bs1,bs2);
    d=t.stop();
    std::cout<<bs3.to_string<char,std::char_traits<char>,std::allocator<char> >()<<std::endl;
    std::cout<<"duration="<<d<<std::endl<<std::endl;

    std::cout<<"Bitset inject with loop"<<std::endl;
    t.start();
    for(int i=0;i<nbIter;++i)
        injectLoop<30,10>(bs1Bis,bs2);
    d=t.stop();
    std::cout<<bs1Bis.to_string<char,std::char_traits<char>,std::allocator<char> >()<<std::endl;
    std::cout<<"duration="<<d<<std::endl<<std::endl;


    std::cout<<"Dynamicbitset concat with loop"<<std::endl;
    t.start();
    for(int i=0;i<nbIter;++i)
        bs3D=concatLoopDyn(bs1D,bs2D);
    d=t.stop();
    std::string s;
    to_string(bs3D,s);
    std::cout<<s<<std::endl;
    std::cout<<"duration="<<d<<std::endl<<std::endl;


    std::cout<<"Dynamicbitset inject with loop"<<std::endl;
    t.start();
    for(int i=0;i<nbIter;++i)
        injectLoopDyn(bs1DBis,bs2D,20);
    d=t.stop();
    to_string(bs1DBis,s);
    std::cout<<s<<std::endl;
    std::cout<<"duration="<<d<<std::endl<<std::endl;

    std::cout<<"Dynamicbitset concat with operators"<<std::endl;
    t.start();
    for(int i=0;i<nbIter;++i)
        bs3D=concatOperatorsDyn(bs1D,bs2D);
    d=t.stop();
    to_string(bs3D,s);
    std::cout<<s<<std::endl;
    std::cout<<"duration="<<d<<std::endl<<std::endl;


    std::cout<<"Dynamicbitset concat with strings"<<std::endl;
    t.start();
    for(int i=0;i<nbIter;++i)
        bs3D=concatStringDyn(bs1D,bs2D);
    d=t.stop();
    to_string(bs3D,s);
    std::cout<<s<<std::endl;
    std::cout<<"duration="<<d<<std::endl<<std::endl;

}

您可以注意到,我使用循环编写的函数会产生不同的结果。这是因为我在编写时将第二个位集的lsb放在第一个位集的msb之后(lsb在右侧)。使用字符串或“位运算符”函数您只需切换调用参数。

我运行了一个测试,比较了以下两种方法:

  /* ... */
  for( int ii = 0; ii < 1000000; ++ii ) {
    std::bitset<16> v1( randomUlongs[ii] );
    std::bitset<16> v2( randomUlongs[ii+1] );
#ifdef STRING_TEST
    std::bitset<32> v3( v1.to_string() + v2.to_string() );
#else
    std::bitset<32> v3( v2.to_ulong() | (v1.to_ulong() << 16) );
    /* print out v3 */
  }
在Linux(x86_i686)下,GCC4.4.6的优化级别为3:字符串连接速度最快,为2倍

>在Solaris(SPARC)中,<>代码> GCC 3.4.3和,两者都具有优化级别3:非字符串方法最快10倍。


我想你会找到“最快的”解决方案高度依赖于编译器,尽管我认为平台也可以发挥重要作用。

我不知道。您想要性能,但随后使用字符串作为位字段,在堆上分配内存。不知何故,这不匹配-将两者连接在一起不会成为性能问题。在上述samp中使用字符串le代码只是为了给出一个可读性好的示例。我认为使用字符串1111和00可以很容易地读取111100。上面的代码不起作用,因为在使用运算符|=时,两个位集必须具有相同的长度。当初始化第二个位集的副本并调整其大小时,它也会起作用。如果有,我已将代码上载到pastebinne感兴趣:“PreciseTimer”只是一个实用程序类,用于使用我们在工作中使用的窗口上的性能计数器计算ellapsed时间。如果需要,您可以将其替换为posix时间测量。
Bitset concat with strings
111111111100000000000000011111
duration=0.000366713

Bitset concat with loop
000001111111111111110000000000
duration=7.99985e-006

Bitset inject with loop
000001111111111111110000000000
duration=2.87995e-006

Dynamicbitset concat with loop
000001111111111111110000000000
duration=0.000132158

Dynamicbitset inject with loop
000001111111111111110000000000
duration=3.19994e-006

Dynamicbitset concat with operators
111111111100000000000000011111
duration=0.000191676

Dynamicbitset concat with strings
111111111100000000000000011111
duration=0.000404152
  /* ... */
  for( int ii = 0; ii < 1000000; ++ii ) {
    std::bitset<16> v1( randomUlongs[ii] );
    std::bitset<16> v2( randomUlongs[ii+1] );
#ifdef STRING_TEST
    std::bitset<32> v3( v1.to_string() + v2.to_string() );
#else
    std::bitset<32> v3( v2.to_ulong() | (v1.to_ulong() << 16) );
    /* print out v3 */
  }
~ time for ((ii=0; ii<1000; ii++)); do ./bitset_test >/dev/null; done