# Better way to convert decimal float into special hexadecimal notation

Stack Overflow Asked by MYZ on January 1, 2021

I have decimal numbers in the range between 0 and ~15.9 and want to convert them into a specific hexadecimal notation.
So the special notation goes like this:
There are 16 bits. The first 4 bits are for the pre-decimal-point position. The next 12 bits are for the decimal places.

A * 16^0 + B * 16^{-1} + C * 16^{-2} + D * 16^{-3}

Here is how I am doing it now in C++ (I am "brute forcing" it. Just check how often 16 fits in A, then check how often 1/16 fits in B and so on):

uint16_t dec_to_special_hex(double x){
uint16_t A, B, C, D;
A = static_cast<uint16_t>(x);
if (A > 15)
return 65535;

double remainder = x - A;    //get decimal places
B = static_cast<uint16_t>(remainder * 16);
remainder = remainder - B * (1 / 16);
C = static_cast<uint16_t>(remainder * 16 * 16);
remainder = remainder - C * (1 / (16 * 16));
D = static_cast<uint16_t>(remainder * 16 * 16 * 16);
remainder = remainder - D * (1 / (16 * 16 * 16));

uint16_t temp, ret = A;
ret = ret << 12;
temp = B << 8;
ret = ret | B;
temp = C << 4;
ret = ret | C;
ret = ret | D;
return ret;
}


I wounder if there is no better, more elegant way to do this. I am looking at the digits I am handling and it just feels like there must be more to it, but I could not find a better way yet.
Would be happy for your suggestions!

I wounder if there is no better, more elegant way to do this

Elegant is subjective, but:

One thing you can do is work with the bits directly. Check this simple converter to see how IEEE floating point numbers work (if you don't know already). Then look at this question for a method to get the different groups of bits of a floating point number (the answer therein is for a float type, but the conversion to double is simple).

After you have the bits, All you need to do is shift the mantissa, depending on the exponent, and perform bit-wise & with different windows to get the bits for A, B, C and D.

Correct answer by Benny K on January 1, 2021

Assuming you just wish to truncate and not round, this can be done with:

uint16_t dec_to_special_hex(double x)
{
return
x < 0   ?     0 :
16 <= x ? 65535 :
4096*x;
}


Answered by Eric Postpischil on January 1, 2021