jero2rome
jero2rome

Reputation: 1568

convert 64-bit binary string representation of a double number back to double number in c++

I have a IEEE754 Double precision 64-bit binary string representation of a double number. example : double value = 0.999; Its binary representation is "0011111111101111111101111100111011011001000101101000011100101011"

I want to convert this string back to a double number in c++. I dont want to use any external libraries or .dll's as my program would operate in any platform.

Upvotes: 7

Views: 5909

Answers (5)

AProgrammer
AProgrammer

Reputation: 52274

my program would operate in any platform

Included I assume those whose double format isn't IEEE. Something like this should work:

#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;

Upvotes: 0

fredoverflow
fredoverflow

Reputation: 263078

C string solution:

#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 solution:

#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;
}

generic solution:

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;
}

example calls:

#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';
}

Note: I assume unsigned long long has 64 bits. A cleaner solution would be to include <cstdint> and use uint64_t instead, assuming your compiler is up to date and provides that C++11 header.

Upvotes: 12

sehe
sehe

Reputation: 392853

Ignoring byte-ordering issues, but I suppose this should be a viable option:

The below has an outcome of .999 on i386 with gcc. See it live: 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;
    }
}

Upvotes: 0

Hot Licks
Hot Licks

Reputation: 47699

Is it really a character string of binary bits? If so, first convert to a 64-bit int. Then either use a library routine (probably there is one somewhere), or more simply, use a double aliased over the 64-bit int to convert to double.

(If it's already a 64-bit int then skip the first step.)

Upvotes: 0

Luchian Grigore
Luchian Grigore

Reputation: 258548

A starting point would be to iterate through the individual characters in the string and set individual bits of an existing double.

Upvotes: 1

Related Questions