How many distinct float values?

J

Johnathan Doe

I can google search to find the range of values that can be represented
in a float by reading up on the IEEE std, but is that the same as how
many distinct values that can go in a float type?

For instance, floats can distinguish 0.000001 and 0.000002. If I
started with 0.000001 and kept adding 0.000001 until I hit some maximum
value (FLT_MAX?) and kept a counter of how many times I added 0.000001,
would I have a count of how many distinct values can go in a float? And
would that be the same thing as FLT_MAX - FLT_MIN?

Thanks very much.
Johnathan
 
G

Gordon Burditt

I can google search to find the range of values that can be represented
in a float by reading up on the IEEE std, but is that the same as how
many distinct values that can go in a float type?

No. The distance between representable floating-point numbers is
not constant because, well, the binary (or decimal) point floats.

If it's a 32-bit floating point number, you can represent AT MOST
2**32 bit patterns. Subtract one for negative zero, which has the
same value as positive zero. Subtract more for NaNs (and this
depends on just how many different NaN values you think are distinct)
and infinities. Subtract more for denormal values which duplicate
non-denormal values or each other. In any case the number of
distinct values is likely to be somewhat more than 98% of 2**32 but
less than 100% of 2**32.
For instance, floats can distinguish 0.000001 and 0.000002. If I
started with 0.000001 and kept adding 0.000001 until I hit some maximum
value (FLT_MAX?) and kept a counter of how many times I added 0.000001,
would I have a count of how many distinct values can go in a float? And

No. And you would likely NEVER REACH FLT_MAX.

Consider, for example, decimal floating point with exactly 6 decimal
digits of precision. You start off with 0.000001, and keep counting
until you get 1.000000. At that point, 1.000000 + 0.000001 =
1.000000, so you quit getting different answers. This happens even
if you've got enough exponent to represent 1.000000 e+100.

Note that adjacent representable numbers in this decimal floating
point are 1e+94 apart for .999999e+100 and .999998e+100, but
one millionth apart for .999999e+00 and .999998e+00 .
would that be the same thing as FLT_MAX - FLT_MIN?

No. And on even unreasonable floating point systems,
FLT_MAX - FLT_MIN == FLT_MAX.

Gordon L. Burditt
 
C

CBFalconer

Johnathan said:
.... snip ...

For instance, floats can distinguish 0.000001 and 0.000002. If I
started with 0.000001 and kept adding 0.000001 until I hit some
maximum value (FLT_MAX?) and kept a counter of how many times I
added 0.000001, would I have a count of how many distinct values
can go in a float? And would that be the same thing as FLT_MAX -
FLT_MIN?

float f, inc;
unsigned long ct, overct;

f = inc = 0.000001;
ct = overct = 0;
while (f < FLT_MAX) {
f = f + inc;
ct++;
if (0 == ct) overct++;
}

can be expected to run for a very long time. Think about it.
 
K

Kevin Bracey

In message <[email protected]>
Johnathan Doe said:
I can google search to find the range of values that can be represented
in a float by reading up on the IEEE std, but is that the same as how
many distinct values that can go in a float type?

For instance, floats can distinguish 0.000001 and 0.000002. If I
started with 0.000001 and kept adding 0.000001 until I hit some maximum
value (FLT_MAX?) and kept a counter of how many times I added 0.000001,
would I have a count of how many distinct values can go in a float? And
would that be the same thing as FLT_MAX - FLT_MIN?

As an additional comment to the other answers you've received, C99 adds
a couple of functions nextafter() and nexttoward() that can be used to
enumerate distinct floating values. This example would count the number of
distinct finite float values:

float f = -FLT_MAX;
long long count = 1;
do
{
f = nextafterf(f, FLT_MAX);
count++;
}
while (f != FLT_MAX);

Anyway, roughly speaking, an IEEE 32-bit single number can hold 2^32
different values, as there are 2^32 different bit patterns for the number.
But more specifically these break down as:

2 zeros (exponent=mantissa=0)
2 infinities (exponent=max, mantissa=0)
16,777,214 NaNs (exponent=max, mantissa<>0)
16,777,214 subnormal numbers (exponent=0, mantissa<>0)
4,261,412,864 normal numbers (0<exponent<max)

The count loop above would count the normals, subnormals and one of the
zeros, so should give 4,278,190,079.

In IEEE, all subnormal and normal numbers are distinct - it's an efficient
representation in that respect. The only "duplicate" coding is +/-0, and that
has its uses in certain infinitesimal convergence calculations - it preserves
the information of which side a cut was approached.
 
K

Keith Thompson

Kevin Bracey said:
In message
<[email protected]> Johnathan


As an additional comment to the other answers you've received, C99 adds
a couple of functions nextafter() and nexttoward() that can be used to
enumerate distinct floating values. This example would count the number of
distinct finite float values:

float f = -FLT_MAX;
long long count = 1;
do
{
f = nextafterf(f, FLT_MAX);
count++;
}
while (f != FLT_MAX);

Anyway, roughly speaking, an IEEE 32-bit single number can hold 2^32
different values, as there are 2^32 different bit patterns for the number.
But more specifically these break down as:
[details snipped]

It's also important to remember that C's type "float" isn't
necessarily an IEEE floating-point type. It almost certainly will be
on any modern machine, but there are still system's with other
floating-point formats (VAX, IBM 370, some older Cray systems, etc.).

In C99, an implementation will define the symbol __STDC_IEC_559__
if it conforms to the IEEE floating-point standard (C99 Annex F).
 
K

Kevin D. Quitt

Memorize the following:

<ftp://ftp.quitt.net/Outgoing/goldbergFollowup.pdf>
 
D

Dik T. Winter

> In IEEE, all subnormal and normal numbers are distinct - it's an efficient
> representation in that respect. The only "duplicate" coding is +/-0, and that
> has its uses in certain infinitesimal convergence calculations - it preserves
> the information of which side a cut was approached.

Yes, I know that Kahan was a big proponent of it (as of the signed
infinities). But you get in problems when you try to implement
standard functions with complex arguments.
 
K

Kevin Bracey

In message <[email protected]>
Keith Thompson said:
In C99, an implementation will define the symbol __STDC_IEC_559__
if it conforms to the IEEE floating-point standard (C99 Annex F).

Although Annex F specifies a lot more than just IEEE 754 conformance. The
implementation I use has been IEEE 754 conformant for years - far more so
than most x86 compilers, but is still some way from meeting all the
requirements of Annex F regarding library functions and pragmas. There's lots
of intricacy there to do with when exceptions get raised etc. So
__STDC_IEC_559__ remains undefined.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top