我有一个双数的IEEE754双精度64位二进制字符串表示。 示例:double value = 0.999; 其二进制表示为“0011111111101111111101111100111011011001000101101000011100101011”
我想将此字符串转换回c ++中的双数字。 我不想使用任何外部库或.dll,因为我的程序可以在任何平台上运行。
答案 0 :(得分:10)
C字符串解决方案:
#include <cstring> // needed for all three solutions because of memcpy
double bitstring_to_double(const char* p)
{
unsigned long long x = 0;
for (; *p; ++p)
{
x = (x << 1) + (*p - '0');
}
double d;
memcpy(&d, &x, 8);
return d;
}
std::string
解决方案:
#include <string>
double bitstring_to_double(const std::string& s)
{
unsigned long long x = 0;
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it)
{
x = (x << 1) + (*it - '0');
}
double d;
memcpy(&d, &x, 8);
return d;
}
通用解决方案:
template<typename InputIterator>
double bitstring_to_double(InputIterator begin, InputIterator end)
{
unsigned long long x = 0;
for (; begin != end; ++begin)
{
x = (x << 1) + (*begin - '0');
}
double d;
memcpy(&d, &x, 8);
return d;
}
示例调用:
#include <iostream>
int main()
{
const char * p = "0011111111101111111101111100111011011001000101101000011100101011";
std::cout << bitstring_to_double(p) << '\n';
std::string s(p);
std::cout << bitstring_to_double(s) << '\n';
std::cout << bitstring_to_double(s.begin(), s.end()) << '\n';
std::cout << bitstring_to_double(p + 0, p + 64) << '\n';
}
注意:我假设unsigned long long
有64位。更简洁的解决方案是包含<cstdint>
并使用uint64_t
代替,假设您的编译器是最新的并提供C ++ 11标头。
答案 1 :(得分:1)
一个起点是迭代字符串中的各个字符并设置现有double
的各个位。
答案 2 :(得分:0)
它真的是二进制位的字符串吗?如果是这样,首先转换为64位int。然后使用库例程(可能有一个地方),或者更简单地说,使用64位int上的double
别名转换为double
。
(如果它已经是64位int,则跳过第一步。)
答案 3 :(得分:0)
忽略字节排序问题,但我认为这应该是一个可行的选择:
以下在i386上使用gcc的结果为.999。现场观看: https://ideone.com/i4ygJ
#include <cstdint>
#include <sstream>
#include <iostream>
#include <bitset>
int main()
{
std::istringstream iss("0011111111101111111101111100111011011001000101101000011100101011");
std::bitset<32> hi, lo;
if (iss >> hi >> lo)
{
struct { uint32_t lo, hi; } words = { lo.to_ulong(), hi.to_ulong() };
double converted = *reinterpret_cast<double*>(&words);
std::cout << hi << std::endl;
std::cout << lo << std::endl;
std::cout << converted << std::endl;
}
}
答案 4 :(得分:0)
我的程序可以在任何平台上运行
包括我假设双格式不是IEEE的那些。这样的事情应该有效:
#include <math.h>
...
int const dbl_exponent_bits = 11;
int const dbl_exponent_offset = 1023;
int const dbl_significand_bits = 52;
bool negative = (*num++ == '1');
int exponent = 0;
for (int i = 0; i < dbl_exponent_bits; ++i, ++num) {
exponent = 2*exponent + (*num == '1' ? 1 : 0);
}
double significand = 1;
for (int i = 0; i < dbl_significand_bits; ++i, ++num) {
significand = 2*significand + (*num == '1' ? 1 : 0);
}
assert(*num == '\0');
double result = ldexp(significand, exponent-(dbl_exponent_offset+dbl_significand_bits));
if (negative)
result = -result;