如何将标准::位集<64>转换为双精度?
How can you convert a std::bitset<64> to a double?
有没有办法在不使用任何外部库(Boost等)的情况下将std::bitset<64>转换为双精度?我正在使用位集来表示遗传算法中的基因组,我需要一种方法将一组位转换为双精度。
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 .
大多数人都试图提供答案,让你把位向量当作直接包含编码的整数或双精度
。我建议你完全避免这种做法。虽然它确实"工作"了,但它到处都是汉明悬崖。您通常希望编码排列内容,以便如果两个解码值彼此靠近,则它们的编码值也彼此靠近。它还强制您使用 64 位精度。
我会手动管理转换。假设您有三个变量要编码,x、y 和 z。例如,您的领域专业知识可用于表示 -5 <= x <5、0 <= y <100 和 0 <= z <1,其中 x 需要 8 位精度,y 需要 12 位精度,z 需要 10 位精度。这为您提供的总搜索空间仅为 30 位。您可以使用一个 30 位字符串,将前 8 个视为编码 x,将下一个 12 视为 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位无论如何都是合适的大小,那么将所有内容填充到本机单词中可能值得额外的开销。否则,我猜你给搜索过程增加的开销可能会压倒你通过更快的编码和解码获得的任何好处。
编辑:: 我已经决定我对此有点愚蠢。虽然你最终得到一个双精度,但它假设位集包含一个整数......这是一个很大的假设。你最终会得到每个位集一个可预测和可重复的值,但我仍然不认为这是作者的意图。
好吧,如果您遍历位值并执行
output_double += pow( 2, 64-(bit_position+1) ) * bit_value;
那会起作用。只要是大端序
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 正在将csv文件读取为双精度矢量
- 我可以信任表示整数的浮点或双精度来保持精度吗
- 如何在C++中的同一函数中使用字符串和双精度
- 特征::矩阵<双精度,1,3> 结构类型函数中的返回类型函数
- 检查是否以特定精度给出双精度
- 转换函数,将 std::数组的双精度作为参数或双精度作为参数单独转换
- C 字符串返回字符串的整数/双精度/长整型值
- 为什么将双精度转换为 int 似乎在第 16 位数字之后将其四舍五入?
- 如何使双精度值的 C++ 和 C# 中的结果相同
- 使用浮点数和双精度数的非常小数字的数学
- 使用 Xcode 将双精度存储在数组C++中
- 在 C++ 中将双精度变量写入二进制文件
- 如何从字符串转换为双精度*
- 为什么我的数组双精度函数不起作用?
- 高精度双精度的 Sprintf 格式化问题
- C++ cout 将双精度对齐到精度 2 并正确对齐
- 将指针数组分配给双精度
- C++如何将字符串逐行转换为双精度
- 长双精度C++是IEEE二进制128的实现吗?