Double from long bits

I have an unsigned long long (or uint64_t ) uint64_t and you want to convert it to double . The double must have the same bit as the long value. That way I can set the bits of the double โ€œmanuallyโ€.

 unsigned long long bits = 1ULL; double result = /* some magic here */ bits; 

I am looking for a way to do this.

+4
source share
4 answers

The portable way to do this is with memcpy (you can also conditionally do this with reinterpret_cast or union, but they are not necessarily portable because they violate the strict restriction letter, alias):

 // First, static assert that the sizes are the same memcpy(&result, &bits, sizeof(bits)); 

But before you make sure you know exactly what you are doing and what kind of floating point representation is used (although IEEE754 is a popular / common choice). You will want to avoid all kinds of problem values, such as infinity, NaN, and denormal numbers.

+13
source

Beware of union and reinterpret_cast<double*>(&bits) , since both of these methods are UB. Pretty much all you can do is memcpy.

+5
source

This is called the pun type โ€” accessing the same object in memory through two different types. In C ++, this is done using reinterpret_cast

 double result = reinterpret_cast<double&>(bits); 

per C ++ 11 standard 5.2.10 / 11 Re-interpret casting [expr.reinterpret.cast] :

An expression lvalue of type T1 can be passed to the type "reference to T2" if the expression of the type "pointer to T1" can be explicitly converted to the type "pointer to T2" using reinterpret_cast. That is, the cast reinterpret_cast <T &> (x) link has the same effect as converting * reinterpret_cast <T *> (& x) with inline and * operators (and similarly for reinterpret_cast <T &> (x)). The result refers to the same object as the lvalue source, but with a different type. The result is an lvalue for the lvalue reference type or an rvalue reference for the function type and an x โ€‹โ€‹value for the rvalue reference for the object type. No temporary copies are created, and constructors (12.1) or conversion functions (12.3) are not called.

Premise:

... if an expression of type "pointer to T1" can be explicitly converted to type "pointer to T2" using reinterpret_cast.

covered in p7 of the same section:

An object pointer can be explicitly converted to an object pointer of another type. When prvalue v of type "pointer to T1" is converted to type "pointer to cv T2", the result is static_cast <cv T2 *> (static_cast <cv void *> (v)), if both T1 and T2 are standard type calculations ( 3.9) and alignment requirements of T2 are not more stringent than the requirements of T1, or if any type is invalid.

0
source

Next, the void pointer is used.

 unsigned long long bits = 1ULL; void* tempPtr=(void*)&bits; double result = *(double*)tempPtr; 
-2
source

Source: https://habr.com/ru/post/1012019/


All Articles