繁体   English   中英

结构和类的C ++按位运算

[英]C++ bitwise operations on structs and classes

我正在开发一个通用的遗传算法库,其中每个生物的染色体是其在记忆中的位表示。 因此,举例来说,如果我想改变一个有机体,我会随机翻转对象本身的位。

起初,我尝试使用C ++标准库中的bitset类,但是,当转换回对象T ,我唯一的选择是使用to_ullong成员函数,这对于具有大于大小的位数的表示来说是一个问题一个unsigned long long

然后我决定在任何对象T上为按位操作创建一个通用库,所以我可以将这些操作直接应用到对象本身,而不是先将它们转换为bitset

所以你可以看到我想要实现的目标,这是来自库的一个函数:

template<typename T>
void flip(T& x, size_t const i)
{
    x ^= 1 << i;
}

它在GA库中使用如下:

template<typename T>
void GeneticAlgorithm<T>::mutate(T& organism, double const rate)
{
    std::random_device rd;
    std::mt19937 mt(rd());

    std::uniform_real_distribution<double> dist(0, 1);

    for(size_t i = 0; i < m_nBits; ++i)
        if(dist(mt) <= rate)
            bit::flip(organism, i);
}

如果这样可行会非常好,但是现在我从VC ++ 2015 RC编译器收到此错误消息:

严重级代码描述项目文件行错误C2677二进制'^':找不到采用类型'T'(或没有可接受的转换)的全局运算符.GeneticAlgorithm path \\ geneticalgorithm \\ geneticalgorithm \\ BitManip.hpp 57

如果我为^更正了这个错误,我会为其他运营商获得更多。

我之前没有在我的代码中使用按位运算符,所以我猜这些运算符不应该与任何对象一起使用? 如果是这样,我怎么能解决这个问题呢?

你想要达到的目标就是这样(参见Peter Schneider的评论):

template<typename T> void flip(T& x, size_t const i) {
    unsigned char* data = reinterpret_cast<unsigned char*>(&x);
    data[i/8] ^= (1 << (i%8));
}

它的作用是将数据x重新解释为一个字节数组(unsigned char),然后确定应该翻转哪个字节(i / 8),然后确定字节中的哪个位(i%8)。

注意:此外,在函数开头添加可能是安全的:

assert(i < sizeof(T)*8)

我的印象是你还没有完全理解C ++提供的面向对象特性。 (当来自C中更加以数据为中心的编程时,这并非不典型.C ++专门设计用于以期望的速度进行转换并使其无痛。)

我的建议是将翻转操作封装在生物体中,让生物体处理它。 作为说明(未经测试,但编译):

#include<climits>  // CHAR_BIT
#include<cstdlib>  // exit()

class string;
void log(const char *);

// inaccessible from the outside
constexpr int NUM_TRAITS = 1000;
constexpr size_t TRAIT_ARR_SZ = (NUM_TRAITS+CHAR_BIT-1)/CHAR_BIT;

class Organism
{ 

    char traits[TRAIT_ARR_SZ];
    int flips[NUM_TRAITS];

    /////////////////////////////////////////////////////////////
    public:

    Organism()  {  /* set traits and flips zero */  }

    // Consider a virtual function if you may derive 
    /** Invert the trait at index traitIndex */
    void flipTrait(int traitIndex)
    {
        if( traitIndex >= NUM_TRAITS ) { log("trait overflow"); exit(1); }

        int charInd = traitIndex / CHAR_BIT;
        int bitInd = traitIndex % CHAR_BIT;

        traits[traitIndex] ^= 1 << bitInd;
        flips[traitIndex]++;
    }

    // Organisms can do so much more!
    void display();
    void store(string &path);
    void load(string &path);
    void mutate(float traitRatio);
    Organism clone();
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM