有没有办法转换std :: bitset< 64>没有使用任何外部库(Boost等)的双重?我使用bitset来表示遗传算法中的基因组,我需要一种方法将一组位转换为双精度。
答案 0 :(得分:5)
C ++ 11之路:
union Converter { uint64_t i; double d; };
double convert(std::bitset<64> const& bs) {
Converter c;
c.i = bs.to_ullong();
return c.d;
}
编辑:正如评论中所述,我们可以使用char*
别名,因为它未指定,而不是未定义。
double convert(std::bitset<64> const& bs) {
static_assert(sizeof(uint64_t) == sizeof(double), "Cannot use this!");
uint64_t const u = bs.to_ullong();
double d;
// Aliases to `char*` are explicitly allowed in the Standard (and only them)
char const* cu = reinterpret_cast<char const*>(&u);
char* cd = reinterpret_cast<char*>(&d);
// Copy the bitwise representation from u to d
memcpy(cd, cu, sizeof(u));
return d;
}
to_ullong
仍然需要C ++ 11。
答案 1 :(得分:2)
大多数人都试图提供答案,让您可以将位向量视为直接包含编码的int或double。
我建议你完全避免这种做法。虽然它确实对某些工作定义“起作用”,但却引入了汉明悬崖。您通常希望编码排列,以便如果两个解码值彼此接近,那么它们的编码值也会彼此接近。它还会强制您使用64位精度。
我会手动管理转换。假设您有三个要编码的变量,x,y和z。例如,您的领域专业知识可以用来表示-5&lt; = x&lt; 5,0 <= y&lt; 100和0&lt; = z&lt; 1,x需要8位精度,y需要12位,z需要10位。这为您提供了仅30位的总搜索空间。你可以有一个30位的字符串,将前8个作为编码x,将下一个作为y,将后10作为z。你也可以自由地使用灰色代码来移除汉明悬崖。
我个人过去曾做过以下事情:
inline void binary_encoding::encode(const vector<double>& params)
{
unsigned int start=0;
for(unsigned int param=0; param<params.size(); ++param) {
// m_bpp[i] = number of bits in encoding of parameter i
unsigned int num_bits = m_bpp[param];
// map the double onto the appropriate integer range
// m_range[i] is a pair of (min, max) values for ith parameter
pair<double,double> prange=m_range[param];
double range=prange.second-prange.first;
double max_bit_val=pow(2.0,static_cast<double>(num_bits))-1;
int int_val=static_cast<int>((params[param]-prange.first)*max_bit_val/range+0.5);
// convert the integer to binary
vector<int> result(m_bpp[param]);
for(unsigned int b=0; b<num_bits; ++b) {
result[b]=int_val%2;
int_val/=2;
}
if(m_gray) {
for(unsigned int b=0; b<num_bits-1; ++b) {
result[b]=!(result[b]==result[b+1]);
}
}
// insert the bits into the correct spot in the encoding
copy(result.begin(),result.end(),m_genotype.begin()+start);
start+=num_bits;
}
}
inline void binary_encoding::decode()
{
unsigned int start = 0;
// for each parameter
for(unsigned int param=0; param<m_bpp.size(); param++) {
unsigned int num_bits = m_bpp[param];
unsigned int intval = 0;
if(m_gray) {
// convert from gray to binary
vector<int> binary(num_bits);
binary[num_bits-1] = m_genotype[start+num_bits-1];
intval = binary[num_bits-1];
for(int i=num_bits-2; i>=0; i--) {
binary[i] = !(binary[i+1] == m_genotype[start+i]);
intval += intval + binary[i];
}
}
else {
// convert from binary encoding to integer
for(int i=num_bits-1; i>=0; i--) {
intval += intval + m_genotype[start+i];
}
}
// convert from integer to double in the appropriate range
pair<double,double> prange = m_range[param];
double range = prange.second - prange.first;
double m = range / (pow(2.0,double(num_bits)) - 1.0);
// m_phenotype is a vector<double> containing all the decoded parameters
m_phenotype[param] = m * double(intval) + prange.first;
start += num_bits;
}
}
请注意,由于可能与您无关的原因,我没有使用位向量 - 只是普通的vector<int>
来编码。当然,这段代码中还有许多内容未在此处显示,但您可能会得到基本的想法。
另外需要注意的是,如果你正在进行GPU计算,或者如果你有一个特殊的问题,那么64位是合适的大小,那么把所有东西都塞进原生单词可能是值得的额外开销。否则,我猜你加入搜索过程的开销可能会超过你通过更快的编码和解码获得的任何好处。
答案 2 :(得分:1)
编辑:: 我认为我对此有点傻。虽然你最终得到一个双倍,但它假设bitset包含一个整数...这是一个很大的假设。每个bitset最终会得到一个可预测且可重复的值,但我仍然不认为这是作者的意图。
好吧,如果你迭代位值并执行
output_double += pow( 2, 64-(bit_position+1) ) * bit_value;
那会有用。只要它是big-endian