Unreasonable
Unreasonable

Reputation: 33

conversion - ASCII hex to float in c++

I have a string containing, for example "3F800000".

This is a hexadecimal representation of the float 1.0 Only I can't seem to find any convenient way of making this conversion in C++. Suggestions?

Upvotes: 3

Views: 4185

Answers (3)

vijayst
vijayst

Reputation: 21846

Another way to do this is:

int main() {
    std::string hexString = "3f9d70a4";
    auto long_val = std::stoul(hexString, nullptr, 16);
    cout << *reinterpret_cast<float *>(&long_val);
}

The above code may not work in some compile environments. The below code may work.

union U {
  uint64_t val;
  float f;
};
auto long_val = std::stoul(hexString, nullptr, 16);
U u = { long_val };
std::cout << u.f;

If the above code does not work in your compile environment, try memcpy

float f;
std::memcpy(&f, &long_val, sizeof f);

Upvotes: 0

Aconcagua
Aconcagua

Reputation: 25526

A newer variant, profiting from C++20 and std::bit_cast (#include <bit> for):

static_assert(sizeof(unsigned long) == sizeof(float));
// actually we don't need, std::bit_cast cares for as well
// as long as we let deduce the second template parameter
// from the function argument

auto bitPattern = std::strtoul("3F800000", nullptr, 16);
// or using std::stringstream, sscanf, whichever you prefer...

float value = std::bit_cast<float>(bitPattern);

In contrast to the other answers this is fully legal (not violating strict aliasing rules).

If C++20 is not available we still can use memcpy to legally copy the bit representation from the integral into the floating point variable (as done e.g. here), or, if we are willing to use C in parallel, use a union for type-punning, but this must occur in a C-source as it wouldn't be legal in C++ either.

Upvotes: 1

ephemient
ephemient

Reputation: 204798

Assuming 32-bit int and float,

unsigned int x;
std::stringstream ss;
ss << std::hex << "3F800000";
ss >> x;
return reinterpret_cast<float&>(x);

Upvotes: 6

Related Questions