Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

exact integer range of floating point type

5 views
Skip to first unread message

Kevin Goodsell

unread,
Dec 10, 2002, 4:29:37 PM12/10/02
to
Is there any way to determine the range of contiguous integers that
can be exactly represented by a float or double?

I'm not entirely sure that my question makes sense as written, so I'll
try to clarify. I'm trying to find the range in which a floating point
type can be used basically like an integer type, with calculations
(other than divisions) coming out as exact integers that can be safely
compared for equality. Presumably most floating point representations
have some range of values in which all integers in the range are
exactly representable without skipping any. Adding 1 to any integer in
this range (except the last) would give (exactly) the next largest
integer in the range.

Any thoughts on this problem are welcome. Thanks.

-Kevin

Mr. XXXX

unread,
Dec 10, 2002, 5:32:03 PM12/10/02
to
Kevin Goodsell <good...@bridgernet.com> wrote in
news:icmcvuoil4jttk366...@4ax.com:

Integer numbers in a float/double are rarely stored as 'number.0'. In most
cases there's a (small) crap ('noise') in the fractional part. That can
make an 'a==b' style comparison fail.

If you want to find out the biggest integer that can be stored in a FP type
then check out the 'decimal point precision' stuff in the compiler/machine
manual. If the type has, say, 7 (full) significant digits then I guess it
can store stuff between -9999999 and 9999999 _WITH A NOISE LOWER THAN +-1_.
BUT don't be sure in things like that, say, 70000 times adding 1 to
'2165443.whatever' will make exactly '2235443.whatever'. You may need to do
some adjustments (things with round() and/or casts from/to integer types)
to prevent the noise from accumulating.

IMNSHO the best thing is to run some test code with the stunts you plan to
do.

D a v i d E m r i c h

unread,
Dec 10, 2002, 5:59:40 PM12/10/02
to

"Kevin Goodsell" <good...@bridgernet.com> wrote in message news:icmcvuoil4jttk366...@4ax.com...

As you suggest, over a certain range there is a one-to-one mapping between
integers & FP numbers. Beyond that you will not be able to represent all
sucessive integers as distinct FP numbers.

Roughly speaking it's the same as the range covered by the significand for the FP
format. For single precision IEEE 754-1985, the significand is 24 bits. Double
precision extended it's >=64 bits. Other IEEE FP formats fall within that range.

Look in float.h. The number of significand bits is given by FLT_MANT_DIG,
and DBL_MANT_DIG.

David


Eric Sosman

unread,
Dec 10, 2002, 5:32:45 PM12/10/02
to

Ideally, `pow(FLT_RADIX, xxx_MANT_DIG)' would give the
largest value, which would also be the number of strictly
positive exact integer values. Doubling this (for the
negatives) and adding one (for zero) would give the total
number of exact integers, but this quantity itself would
not be exactly representable in the xxx type.

Also, of course, the pow() function might not be exact;
you might need to resort to repeated multiplication.

Your question, though, reminds me of the dialog in an
old Calvin and Hobbes comic strip: Calvin asks his mother
"Do we have any chainsaws in the house?" She tells him no,
and he walks away grousing "How am I ever going to learn
to juggle?" Are you certain you want to juggle this
particular set of saws?

--
Eric....@sun.com

Christian Bau

unread,
Dec 10, 2002, 6:03:29 PM12/10/02
to
In article <icmcvuoil4jttk366...@4ax.com>,
Kevin Goodsell <good...@bridgernet.com> wrote:

You can't do anything portable; the C Standard wouldn't even guarantee
that there are _any_ integers at all that can be stored exactly in a
float or double variable.

If your implementation uses floating point arithmetic according to the
IEC 60559 standard (this can be tested by checking if __STDC_IEC_559__
is defined), then float can and will represent integers up to pow (2.0,
FLT_MANT_DIG) and double can and will represent integers up to pow (2.0,
DBL_MANT_DIG) exactly, that is up to 2^24 or 2^53.

Dann Corbit

unread,
Dec 10, 2002, 5:44:03 PM12/10/02
to
"Kevin Goodsell" <good...@bridgernet.com> wrote in message
news:icmcvuoil4jttk366...@4ax.com...


#include <math.h>
#include <stdio.h>
#include <float.h>
int main(void)
{
printf("The range of numbers that can be represented exactly on this
machine are 0 to +/- %*.0f\n",
DBL_DIG+1,
pow(2.0, (double) DBL_MANT_DIG)
);
return 0;
}

Even at that, it will be very dangerous to compare for equality. If (for
instance) any intermediate transaction exceeds 2^DBL_MANT_DIG bits, you will
have a ploss. I am sure that there are lots of other things to worry about
as well.
--
C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
"The C-FAQ Book" ISBN 0-201-84519-9
C.A.P. FAQ: ftp://cap.connx.com/pub/Chess%20Analysis%20Project%20FAQ.htm

Eric Sosman

unread,
Dec 10, 2002, 6:30:56 PM12/10/02
to
Christian Bau wrote:
>
> You can't do anything portable; the C Standard wouldn't even guarantee
> that there are _any_ integers at all that can be stored exactly in a
> float or double variable.

It seems to me the Standard guarantees the existence
of such values (5.2.4.2.2 Characteristics of floating types
<float.h>, paragraphs 1 and 2). What doesn't seem to be
a sure thing is whether something like `1.0' will actually
produce such a value.

--
Eric....@sun.com

Tim Prince

unread,
Dec 11, 2002, 2:35:09 AM12/11/02
to
Kevin Goodsell wrote:

#include <float.h>
1/FLT_EPSILON, 1/DBL_EPSILON have the property you describe, with any
reasonable floating point arithmetic.

--
Tim Prince

R124c4u2

unread,
Dec 11, 2002, 8:17:38 AM12/11/02
to
Tim Prince writes:

>> Is there any way to determine the range of contiguous integers that
>> can be exactly represented by a float or double?
>>
>> I'm not entirely sure that my question makes sense as written, so I'll
>> try to clarify. I'm trying to find the range in which a floating point
>> type can be used basically like an integer type, with calculations
>> (other than divisions) coming out as exact integers that can be safely
>> compared for equality. Presumably most floating point representations
>> have some range of values in which all integers in the range are
>> exactly representable without skipping any. Adding 1 to any integer in
>> this range (except the last) would give (exactly) the next largest
>> integer in the range.

>#include <float.h>


>1/FLT_EPSILON, 1/DBL_EPSILON have the property you describe, with any
>reasonable floating point arithmetic.

The OP speaks of range but then, IMO, describes another problem, that which
one might call "granularity". There used to be several numbers that ended up
being printed as, (made up), 4.999999999... Some of these numbers did *not*
have the properties of 1/3 in the decimal system. I think the OPs question
excludes 1/3 anyway. It is clear that he meant to.

So where did these numbers go? They are not there and haven't been there for
several years. This item is on a very long list of questions I don't know the
answer to. My *theory* is that in a modern compiler conversion routines such
as %f detect these numbers somehow and "round" them. For lack of a better
word, it is not what I consider a proper rounding.

AFAIK all decimal numbers can not be represented in a binary computer by the
forms of reresentation used for floating point. But that does not preclude the
possiblilty that there is a *unique* (but wrong) representation for all such
numbers and therefore satisfy the OPs end requirements. That is, a compare
will always yield the right answer.

As a WAG, 1 or 5 might be examples of "bad numbers". Historically 0 can not
be represented in floating point and a certain representation (all zero bits)
was *defined* as 0. But a regular on this NG informed me that it now can be
represented. I didn't have the time to follow up on his assertion.
I had the feeling that following up would almost certainly end up with strong
implications that I was a stupid dolt and I didn't care to go there.

--osmium

Dan Pop

unread,
Dec 11, 2002, 9:02:46 AM12/11/02
to
In <3DF66B8D...@sun.com> Eric Sosman <Eric....@sun.com> writes:

>Kevin Goodsell wrote:
>>
>> Is there any way to determine the range of contiguous integers that
>> can be exactly represented by a float or double?
>>
>> I'm not entirely sure that my question makes sense as written, so I'll
>> try to clarify. I'm trying to find the range in which a floating point
>> type can be used basically like an integer type, with calculations
>> (other than divisions) coming out as exact integers that can be safely
>> compared for equality. Presumably most floating point representations
>> have some range of values in which all integers in the range are
>> exactly representable without skipping any. Adding 1 to any integer in
>> this range (except the last) would give (exactly) the next largest
>> integer in the range.
>
> Ideally, `pow(FLT_RADIX, xxx_MANT_DIG)' would give the
>largest value, which would also be the number of strictly
>positive exact integer values.

It's probably safer not to use the last bit of the mantissa, to avoid the
surprises caused by the rounding mode, so I'd recommend dividing this
value by 2. Call me paranoid :-)

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan...@ifh.de

Dan Pop

unread,
Dec 11, 2002, 9:05:46 AM12/11/02
to

>In article <icmcvuoil4jttk366...@4ax.com>,
> Kevin Goodsell <good...@bridgernet.com> wrote:
>
>> Is there any way to determine the range of contiguous integers that
>> can be exactly represented by a float or double?
>>
>> I'm not entirely sure that my question makes sense as written, so I'll
>> try to clarify. I'm trying to find the range in which a floating point
>> type can be used basically like an integer type, with calculations
>> (other than divisions) coming out as exact integers that can be safely
>> compared for equality. Presumably most floating point representations
>> have some range of values in which all integers in the range are
>> exactly representable without skipping any. Adding 1 to any integer in
>> this range (except the last) would give (exactly) the next largest
>> integer in the range.
>
>You can't do anything portable; the C Standard wouldn't even guarantee
>that there are _any_ integers at all that can be stored exactly in a
>float or double variable.

The floating point model used by the standard certainly does.

Dan Pop

unread,
Dec 11, 2002, 9:10:18 AM12/11/02
to
In <at5qn...@enews1.newsguy.com> "Dann Corbit" <dco...@connx.com> writes:

>#include <math.h>
>#include <stdio.h>
>#include <float.h>
>int main(void)
>{
> printf("The range of numbers that can be represented exactly on this
>machine are 0 to +/- %*.0f\n",
> DBL_DIG+1,
> pow(2.0, (double) DBL_MANT_DIG)

^^^
Where does this magical constant come from?

Last time I checked, FLT_RADIX was implementation-defined.

CBFalconer

unread,
Dec 11, 2002, 12:45:54 PM12/11/02
to
Dan Pop wrote:
> Eric Sosman <Eric....@sun.com> writes:
>
... snip ...

> >
> > Ideally, `pow(FLT_RADIX, xxx_MANT_DIG)' would give the
> > largest value, which would also be the number of strictly
> > positive exact integer values.
>
> It's probably safer not to use the last bit of the mantissa, to
> avoid the surprises caused by the rounding mode, so I'd recommend
> dividing this value by 2. Call me paranoid :-)

I think you just assumed FLT_RADIX == 2. Try (xxx_MANT_DIG - 1).
"Paranoidier" :-).

--
Chuck F (cbfal...@yahoo.com) (cbfal...@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!


Dan Pop

unread,
Dec 12, 2002, 8:00:05 AM12/12/02
to
In <3DF76A95...@yahoo.com> CBFalconer <cbfal...@yahoo.com> writes:

>Dan Pop wrote:
>> Eric Sosman <Eric....@sun.com> writes:
>>
>... snip ...
>> >
>> > Ideally, `pow(FLT_RADIX, xxx_MANT_DIG)' would give the
>> > largest value, which would also be the number of strictly
>> > positive exact integer values.
>>
>> It's probably safer not to use the last bit of the mantissa, to
>> avoid the surprises caused by the rounding mode, so I'd recommend
>> dividing this value by 2. Call me paranoid :-)
>
>I think you just assumed FLT_RADIX == 2.

Nope, I have assumed FLT_RADIX == 2 ** N, with N >= 1.

>Try (xxx_MANT_DIG - 1).

You lose too much of the available range this way, if FLT_RADIX has the
other "popular" value, 16.

0 new messages