Float comparison

K

Keith Thompson

CBFalconer said:
x is a double. So is the expression (1.0). So they represent the
same range.
[...]

I think you're saying that the above code may not print "Oops!",
but you didn't actually say so. Can you confirm that?

In the following, I will ignore NaNs and infinities.

So in your model, (x < y) must yield 0 if both x and y represent
the same range, even though some values in the range of x are less
than some values in the range of y. Presumably (x < y) yields 1 if
and only if each value in the range of x is less than each value
in the range of y. And (x == y) if and only if both ranges are
exactly the same. Is that correct?

Is it ever possible for one floating-point value's range to be a
proper subset of another floating-point value's range? May two
such ranges ever overlap without being identical?

The standard clearly states that the accuracy of floating-point
*operations* is implementation-defined (C99 5.2.4.2.2p5).
It makes no such statement about the accuracy or range of stored
floating-point values. Is the range represented by a stored
floating-point value implementation-defined? May the range be wide
enough to include other exactly representable floating-point values?
For example, may the range represented by the stored value 1.0
include 1.0+DBL_EPSILON? If not, what in the standard forbids it?
What exactly are the bounds of the range represented by the stored
value 1.0?

I encourage you to answer these questions with reference to the
standard, not based on what you think the answers *should* be.

If the standard intended each floating-point value to represent a
range, wouldn't it clearly answer questions like these? Why doesn't
it?

Assume, for the sake of argument, a language very similar to
(your conception of) C, except that each floating-point number
represents a single real value (actually a rational value) rather
than a range of values. Do you agree that such a language would
be consistent, even if you dislike it? Can you present a program
that would behave differently in this hypothetical language than in
(your conception of) C? To be clear, this "hypothetical language"
is, in my opinion, simply standard C.
 
K

Keith Thompson

Beej Jorgensen said:
I'm going to speak out of turn here, but I think part of the issue is
how much of this error is presumed to exist in the result. And I don't
know that the standard really addresses this issue; it seems to be more
of a human-interpreted thing.

My position is that *none* of this error exists in a stored value. A
stored FP value represents a real value; it has no way of representing
an error or range.

[...]
With all that in mind, consider:

A: "x means 1.0."
B: "x means everything around 1.0 within some unrepresentable margin
of error."

Does statement B violate the standard in some way? (This is a genuine
question. I'm looking, but not finding it, or anything that mentions
it.)

The standard presents a clear model for floating-point numbers in the
first 2 or 3 paragraphs of 5.2.4.2.2. Note particularly paragraph 2,
which says that a floating-point number x *is equal to* the given
forumula. I see no room there for a model in which a floating-point
number represents a range. (That's actually something I didn't know
when I first entered this discussion.)

On the other hand, it could depend on what "means" means. You're free
to interpret 1.0 as the range (0.5, 1.5) if it's convenient for your
application. But that's not the same thing as what the standard
actually says 1.0 *is*.
 
P

Phil Carmody

CBFalconer said:
Try thinking about it. For example, if I write:

float x = 1.0/3.0;

you are claiming the value stored is 1/3.


Personally, I have no qualms at calling that out for being a
downright lie. Richard made no such claim at all. His claim is
clear. Your reading comprehension is pitiful.
Things may be worse, but they won't be better.

Until your news provider starts denying your posts.

Phil
 
D

David Thompson

No, although it may be so used. It is intended to handle integers,
and, except for division, the set of integers is closed under
elementary arithmetic. People are quite familiar with the idea
that a division results in a quotient and a remainder, under which
condition the integer set remains closed.
So are the reals with the same exception.

But the bounded computer/C types int, long etc. aren't closed for
addition/subtraction and multiplication. (And with usual 2sC not quite
for negation.) The C unsigned integer types are closed (except
zerodiv) only because they implement Z sub N rather than Z.
You can't make these statements about FP values.

Computer (non-bignum*) integers are not the mathematical ones any more
than computer floats are mathematical reals. Although it seems in
practice programmers are more often able to cope with the deficiences
of almost-integers better than they do with almost-reals.

* Technically bignums aren't perfect either, but they're good enough
that they only break when you try to break them, whereas 32-bit and
64-bit break in some real programs if you're just a little careless.
We (at least I) don't have enough experience yet with 128 to see if it
is reliably big enough, but I'm not betting the farm on it today.
 
J

James Kuyper

CBFalconer said:
Try thinking about it. For example, if I write:

float x = 1.0/3.0;

you are claiming the value stored is 1/3.

He has repeated and very clearly stated that he does not claim that the
value stored is exactly one-third. However, whatever value is the result
of that calculation, after conversion to float, is the unique value
stored in x. That is the value which must be retained until overwritten
or the end of the lifetime of x, whichever occurs first.

But if you examine the
value stored you will not find that. You will find something in
the range x*(1+FLT_EPSILON) and x*(1-FLT_EPSILON).

No. The value you will find is x, exactly as specified by formula given
in 5.2.4.2.2p2, a formula that does not allow for a range of values, but
only one specific value.

The value of x might or might not be somewhere between
(1.0/3.0)(1-FLT_EPSILON) and (1.0/3.0)(1+FLT_EPSILON) - the standard
makes no such requirements. It could be 12345.6789, for all that the
standard has to say about it. IEEE/IEC 754 makes stricter requirements
(it would be pretty difficult to make more lenient ones!), so if
__STDC_IEC_754__ is predefined for a C99 implementation, you can
actually rely upon x to be reasonably close to the mathematical value of
1/3. But whatever value x represents is a single specific value, the one
given by 5.2.4.2.2p2. Interpreting that value as the center of range
extending from the previous representable value to the next
representable value is an issue for the user to decide upon, not
something that is imposed by either the hardware or the standard.
 
B

BartC

CBFalconer said:
x is a double. So is the expression (1.0). So they represent the
same range. However in:

double x = 1.0;
if (x < (2.1 - 1.1) puts ("Oops!");
if (x > (2.1 - 1.1) puts ("Oops!");

I don't think you have any complaint.

Did you mean exactly 2.1 and 1.1 here, or the ranges 2.05 to 2.15 and 1.05
to 1.15?
 
D

Dik T. Winter

>
> If you are trying to say that the computation may have errors
> larger, even much larger, than that intrinsic in the fp
> representation, I agree entirely.

I am saying that, and so viewing floating-point as an exact representation
of a subset of the rational numbers is much more useful than viewing it as
an inexact representation of the reals. For one thing the first makes
error analysis much easier, and second, it makes it much easier to actually
*define* how f-p works (like in the IEEE standard).
 
B

Beej Jorgensen

Keith Thompson said:
The standard presents a clear model for floating-point numbers in the
first 2 or 3 paragraphs of 5.2.4.2.2. Note particularly paragraph 2,
which says that a floating-point number x *is equal to* the given
forumula.

I've been looking at a draft, but it says "A floating-point number (x)
is defined by the following model", which is pretty strong... I'm not
sure of the difference between that and "is equal to".
I see no room there for a model in which a floating-point number
represents a range.

I think the perceived implicit "range" or "wiggle room" is what you're
left with after you remove the set of numbers defined by the model (with
finite p) from the set of real numbers.

Maybe the correct way to address these missing numbers is as "not
defined by the standard", since we're talking about (in the equation)
values of k that exceed p.

So maybe what could be said is that there is a real gap between A and
the next highest representable number B, and the standard doesn't define
(or make a statement about) that gap.

Those two last paragraphs are pretty thin; I could use some
verification.
On the other hand, it could depend on what "means" means. You're free
to interpret 1.0 as the range (0.5, 1.5) if it's convenient for your
application.

I really feel this is the crux of the issue. (For instance, maybe
saying "there is a real gap between 1.0 and the next representable
floating point number" isn't as offensive as saying "each floating point
number can only be narrowed down to a certain range", though in some
ways they say the same thing.)

It's an interesting diversion in any case.

-Beej
 
C

CBFalconer

Keith said:
CBFalconer said:
Keith Thompson wrote:

... snip ...


x is a double. So is the expression (1.0). So they represent
the same range.
[...]

I think you're saying that the above code may not print "Oops!",
but you didn't actually say so. Can you confirm that?

As written, yes. With the modification I wrote, no.
In the following, I will ignore NaNs and infinities.

So in your model, (x < y) must yield 0 if both x and y represent
the same range, even though some values in the range of x are less
than some values in the range of y. Presumably (x < y) yields 1 if
and only if each value in the range of x is less than each value
in the range of y. And (x == y) if and only if both ranges are
exactly the same. Is that correct?

No. If x and y contain the identical ranges, there are no values
in the x range outside the y range, and vice-versa. So your
statement is impossible. The only thing that controls the ranges
is the value in x (or y). The actual size of the ranges is FP
system dependant.
 
C

CBFalconer

Dik T. Winter said:
(e-mail address removed) writes:
.... snip ...

I am saying that, and so viewing floating-point as an exact
representation of a subset of the rational numbers is much more
useful than viewing it as an inexact representation of the reals.
For one thing the first makes error analysis much easier, and
second, it makes it much easier to actually *define* how f-p
works (like in the IEEE standard).

I disagree. What is useful depends on the use to which you put the
results. However the innate construction of FP values is such that
the 'range' always exists. That range may be so small that you can
afford to ignore it, but you can't just arbitrarily ignore it.

For example the number of different values is, at most, the binary
number expressed by the size of a float. For each such value you
can express the central value, in some form, and the next and
previous values. You can order them all (again, ignoring NANs and
INFs etc.). YOU CAN'T express any value outside that list, but the
available 'range' around the values allows you to REPRESENT any
value sufficiently well to perform calculations.
 
C

CBFalconer

David said:
So are the reals with the same exception.

True, but we are talking about FP representation (and int
representation), which have other limitations, including maximum
and minimum values. ints don't have a range associated with each
value, the adjacent integer value is always available. Reals don't
have an adjacent value, but rationals do (they are countable). The
FP system is built on rationals, but cannot express the adjacent
rational. Neither the integer nor the FP system can handle the
infinities that exist in arithmetic.
 
B

Beej Jorgensen

CBFalconer said:
As long as you agree that you are considering the actual program,
and not just the value found in the double object x.

I think so. After all, the value found in x is merely 1.0; I believe
it's undisputed. As for how it got there or what it means, I can't say.

-Beej
 
C

CBFalconer

William said:
How is this statement any less absurd than the claim that
int x = 1/3; is a "claim that the value stored is the
multiplicative inverse of 3"? (Spelling it out long hand
to avoid the ambiguity between the integer value 0 and the
mathematical concept of 1/3.)

You snipped the whole explanation. I recommend you don't snip in
the middle of paragraphs.
 
P

Phil Carmody

Richard Heathfield said:
Phil Carmody said:


No, it's true. I see no difference between:

float x = 1.0/3.0;

and

float x = 1/3.;

Apart from different paths on the parse tree.

Are you insinuating that CBF can't even properly punctuate
sentences either, now? You're probably ahead of the curve
picking up on that, but you'll probably be right in a few
years.

If he were to post something ending "yadda yadda yadda 1/3?"
would you accuse him of being unable to use ternary operators?

Yes, yes, I know you were simply jesting. So am I.

Phil
 
P

Phil Carmody

Dik T. Winter said:
The fixed/floating point at that time, which would mean with something like
40-bit mantissa.

I still can't translate that into being a binary predicate, alas.

Phil
 
P

Phil Carmody

Beej Jorgensen said:
I think so. After all, the value found in x is merely 1.0; I believe
it's undisputed.

Have you missed the posts to this thread by CBF? He has disputed that!

Phil
 
P

Phil Carmody

CBFalconer said:
Oh? I have a nuclear counter and a sensor. Over a given period T
I detect 10,000 counts of events of more than 1 keV energy. I
compute the expected error in the counts as sqrt(count), or 100 and
store that in cterror. Now you claim that 'counts' is exact, and
represents the radiation strength at the time of testing? You are
telling me to ignore cterror? I haven't even considered the time
resolution of the detection system.

We can switch from/to everything is physics to/from everything is
math, or from/to everything is analog to/from everything is digital
at the drop of a hat (straw). :)

I simply cannot bear to read any more of your irrelevant, incorrect,
and logical-fallacy-splattered (there have probably been more straw
men from you than than posts this thread) drivel. This thread has
been the one that has pushed you as far into crank/loon territory as
some of the classic comp.compression and sci.crypt whack-jobs.

We've known that c.l.c has had its trolls for a long time, but I think
you might be one of the few who can now raise the banner of being
the c.l.c. crank.

I now understand the meaning of "i=i++;", it means Chuck Falconer
might make a sensible post about floating point numbers. Noses are
passe.

Phil
 
K

Keith Thompson

CBFalconer said:
Oh? I have a nuclear counter and a sensor. Over a given period T
I detect 10,000 counts of events of more than 1 keV energy. I
compute the expected error in the counts as sqrt(count), or 100 and
store that in cterror. Now you claim that 'counts' is exact, and
represents the radiation strength at the time of testing? You are
telling me to ignore cterror? I haven't even considered the time
resolution of the detection system.

No, that's not even close to what I'm saying. Now you're bringing
physical measurements into the discussion. This isn't about physical
measurements; it's about stored floating-point values in C programs.

The value stored in 'counts' is exact. It is 10000, no more, no less.
I make no claim whatsoever about the relationship between this stored
value and the radiation strength, or any other physical quantity.

Apparently, in the situation you're talking about, a stored value of
10000 in 'counts' implies that the some physical quantity is believed
to be somewhere in the range 9900 .. 10100.

What does that have to do with the meaning of C floating-point
numbers? I would have assumed that 'count' would be of some integer
type. Are you now claiming that stored integer values are inherently
inexact?
We can switch from/to everything is physics to/from everything is
math, or from/to everything is analog to/from everything is digital
at the drop of a hat (straw). :)

Feel free to explain that more clearly if you like. If not, I'll just
ignore it; I don't have time to guess what it's supposed to mean.
 
K

Keith Thompson

CBFalconer said:
Keith said:
Try thinking about it. For example, if I write:

float x = 1.0/3.0;

you are claiming the value stored is 1/3.
[...]

I don't believe anybody made such a claim. (It's possible only of
FLT_RADIX is a multiple of 3.)

Then you can't claim you know what is stored there.
[...]

I can know what is stored in x by examining the value of x. On my
system, it's 0.3333333432674407958984375. On some other system, it
may be slightly different.

Given the above declaration, the C standard doesn't tell me exactly
*which* exact floating-point value is stored in x; that's
implementation-defined, and even the implementation's definition might
not be enough to determine it. But it does tell me that *some* exact
floating-point value is stored in x, since (barring trap
representations) that's the only thing that possibly *can* be stored
in x.
 

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
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top