Smallest float different from 0.0?

Mark Dickinson dickinsm at gmail.com
Mon Sep 7 19:33:44 CEST 2009

```On Sep 7, 5:08 pm, kj <no.em... at please.post> wrote:
> Hmmm.  This close-to-the-metal IEEE stuff make a "HERE BE DRAGONS!"
> alarms go off in my head...  (What's up with that correction by 1
> to sys.float_info.mant_dig?  Or, probably equivalently, why would
> sys.float_info.min_exp (-1021) be off by 1 relative to log2 of
> sys.float_info.min (-1022)?)

The sys.float_info constants come straight from the standard C
limits defined in float.h.  The C standards choose to describe
floats in the form

sign * 2**exponent * significand

with 0.5 <= significand < 1.0.  (Well, assuming base 2;  the
actual standard is a bit more general than this;  see e.g.
section 5.2.4.2.2 of C99.)

So from C's point of view, the smallest normal value
comes from the minimum exponent (-1021) together with
the minimum significand (0.5), so it's 2**-1021 * 0.5,
or 2**-1022.  Similarly, the max value is (1-2**-53)*2**1024.

It's a bit unfortunate that the IEEE 754 standard prefers
a different normalization, with the exponent chosen so that
the significand is in [1.0, 2.0).  So where IEEE 754-2008
gives emax as 1023, C gives DBL_MAX_EXP as 1024;  both
describing exactly the same format.

> I suppose that
>
> 2**(sys.float_info.min_exp - sys.float_info.mant_dig)
>
> would also work?

Yes.  This all only works for IEEE 754 binary formats,
though.  Most other floating-point formats you're likely
to meet (IBM hex floats, VAX D and G, Cray floats, etc.)
don't have gradual underflow and subnormals.

--
Mark

```