This is essentially a coding question, but I'll try my best to convert the code to logic here
I'm trying to implement float to hex by referring the Python's inbuilt float.hex
Here is a brief of how it's done taking 3740.0 as an example:
- Convert number to exponent and mantissa as $$ 3740.0 = 0.9130859375\times2^{12} $$ so
e=12andm=0.9130859375 - Compute $$ shift = 1 - MAX(DBL\_MIN\_EXP - e, 0)=1$$ and update the mantissa and exponent: $$ m=m\times2^{shift}=(1.826171875)$$ $$ e=e-shift=11$$. FYI,
DBL_MIN_EXP=-1021 - Now straightforward, convert to hex as: $$hex(m)=1.D38$$ Final result = $$hex(3740.0)=0x1.D38p+11=1.d38\times2^{11}$$
Now finally to my main question :) Why do we do step 2 and perform a shift? I see no advantage or overflow case. Also how and why is shift computed the way it is?. Refernce
Notice that as long as $e \geq \text{DBL_MIN_EXP},$ the shift will always be $1.$ The shift only becomes interesting when $e < \text{DBL_MIN_EXP},$ that is, when you are dealing with numbers very close to zero.
In computer floating-point representations, numbers too close to zero result in underflow, not overflow. In the IEEE-754 standard, for any "normal" number you assume that the stored bits represent a binary floating-point number of the form $1.dddd\ldots ddd \times 2^k,$ that is, the significand has integer part $1$ (which is not stored in the computer representation) followed by fractional bits $dddd\ldots ddd,$ which are stored in the mantissa portion of the computer representation. But there is a minimum normal exponent value $m$, below which you get into subnormal (also called denormalized) numbers, which are assumed to be of the form $0.dddd\ldots ddd \times 2^m,$ where again the bits $dddd\ldots ddd$ are stored in the mantissa of the computer representation.
I think what the authors of float.hex are trying to do is to reflect the computer's internal representations of both normal and denormalized numbers in their function's output. Before the shift, the number $m$ will always have a $0$ to the left of the decimal point and a $1$ in the first bit to the right of the decimal point. For normal numbers, they shift the number left one bit so that the leading $1$ will be on the left side of the decimal point and the digits to the right will represent the bits actually stored in the computer.
Once the exponent of the most significant digit $1$ gets small enough, instead of shifting it left one place to get a $1$ bit to the left of the decimal point, they leave it where it is or shift it right, leaving a $0$ to the left of the decimal point. This does not make the result any more or less numerically accurate as a representation, but it would give you a clue that the number was represented in denormalized form in the computer, which is consistent with the idea of using this representation for debugging software.
A little more about how it works:
If $e < \text{DBL_MIN_EXP}$ then $\text{DBL_MIN_EXP} - e > 0$ and
\begin{align} \mathit{shift} &= 1 - \max(\text{DBL_MIN_EXP} - e, 0) \\ &= 1 - (\text{DBL_MIN_EXP} - e) \\ & = e + (1 - \text{DBL_MIN_EXP}) \\ & = e + 1022 \end{align}
(when $\text{DBL_MIN_EXP} = -1021$) and therefore
$$ e - \mathit{shift} = e - (e + 1022) = -1022, $$
that is, the output will be of the form
$$0.hh\ldots hh \times 2^{-1022}$$
where $hh\ldots hh$ are hexadecimal digits. This corresponds to the fact that denormalized double-precision binary floating-point numbers in IEEE-754 are of the form $0.dddd\ldots ddd \times 2^{-1022}.$
The name $\text{DBL_MIN_EXP}$ is a bit misleading, however, since this constant is $1$ greater than the actual minimum exponent allowed in the IEEE-754 representation.