将双数字的64位二进制字符串表示形式转换回c ++中的双数字

时间:2011-12-23 13:19:31

标签: c++

我有一个双数的IEEE754双精度64位二进制字符串表示。 示例:double value = 0.999; 其二进制表示为“0011111111101111111101111100111011011001000101101000011100101011”

我想将此字符串转换回c ++中的双数字。 我不想使用任何外部库或.dll,因为我的程序可以在任何平台上运行。

5 个答案:

答案 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;