Reputation: 33
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
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
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
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