Float comparison

U

user923005

"Most of them" seems perfectly reasonable to me.

I would have preferred the phrase:
"Floating point numbers in the C language store an infinitesimal
proportion of the fractional numbers."

They don't actually store *any* real numbers except for those which
also happen to be contained in that certain miniscule proportion of
the fractional numbers actually representible in floating point {a
tiny subset of a tiny subset}.

On the other hand, the values that are representible in floating point
tend to be useful in practice.

And a number system that could actually store all true floating point
values would be "rather bulky."
 
P

Phil Carmody

CBFalconer said:
You are wrong,

I just evaluated
fabs ( Richard's_Statement - truth) < c.l.c_Epsilon
and it came to 1.
because that floating point value makes no assertion
about any exact value.

No C variable or value makes any assertions about anything at all.
It only asserts that the real value is
between established limits. Any other assertion comes from other
facts, such as the overall program structure. If you don't realize
this you will make serious usage errors.

Are C integers exact?

What's four divided by three?

Phil
 
P

Phil Carmody

CBFalconer said:
No. Try compiling and running this, and explain the results.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
double d1 = 2.0, d2 = 6.0, d3 = 3.0, da, db, dc;

da = d1/d3;
db = d1/d2;
dc = d3 * db;
printf("da = %f, db= %f dc= %f\n", da, db, dc);
printf("da == (2 * db) = %d\n", (da == (2 * db)));
printf("((dc - 1.0) == 1) = %d\n", (dc - 1.0) == 1);
return 0;
}

The output is irrelevant. The *computations* are not necessarily
exactly equal to the numeric result of the identical operations
in the reals, and the storing of the results of the computations
back into the floating point variables may not preserve the same
values which are the results of those computations, but once
the values are stored in those variables, their value is exact.

You are confusing accuracy and precision. The values are exactly
as precise as the completely precise expression given in the C
standard (5.2.4.2.2p2) for the numerical value of floating point
values. They just may not be particularly accurate.

You are also conflating the operations and the values that they
yield.

Phil
 
P

Phil Carmody

You can't. You can only see if two floats are very close to each other.

No, you can test whether they're equal. Generally this won't
correspond perfectly to whatever they represent being equal, but the
floats can be equal.
Absolutely.
pseudocode:

if ((x-y) < SMALL_DIFFERENCE) return true;

Don't use this kind of comparison in a sort algorithm (e.g. in the
compar() function for qsort). It won't work reliably, since it does
not define a total order. Use ==, possibly after checking for NaNs.[/QUOTE]

Yikes - I'd hope there would be a bit of '<' or '>' in there too!

Phil
 
P

Phil Carmody

*most of them*! I think you understating the case by amounts that
require hewbrew letters to express

But we're not on comp.lang.aleph-null, we're on comp.lang.c!

Phil
 
B

BartC

Mark said:
Um, having worked in the sector for fifteen years, I incline to
disagree. If you want to compare two floating-point values then you
should compare the absolute difference to some defined tolerance
criterion.
What is true is that often you don't actually want to compare two such
numbers at all, you just think you do. An example might be whether a
third of 101 lire was the same as a twentieth of 679 lire. It was.

I make that 33 2/3, and 33 19/20. I would say they were different, unless
you're rounding to whole lire first.
 
B

Ben Bacarisse

Mark McIntyre said:
Mark said:
On 21/04/09 11:18, Alessio Ribeca wrote:

Thank you, How can I check for [floating-point] equality ?

You can't. You can only see if two floats are very close to each other.

This bit of nonsense has cropped up more than once in this
thread, so I'm very much afraid people may believe it. But it's
still nonsense!

I disagree.
But strict equality *is* testable in C, if you want to do it,
and don't listen to anyone who tries to tell you otherwise.

And don't listen to anyone who tells you its safe to use == to compare
floats. Really Eric, I'm shocked. Is this you, or a sockpuppet.

I disagree. Ages ago (I say this only to excuse the inevitable errors
that my memory will introduce) I wrote a package for doing interval
arithmetic. A number like 0.1 would be represented by the smallest
representable interval that contains 0.1.

Sometimes the user knows an input number is both perfectly accurate
and representable (for example the power in the inverse square law can
be taken to be 2). There was a notation for this (I forget) that
created an interval of zero width. The arithmetic algorithms were
much faster if this case was given special treatment (usually you need
half the number of operations) which of course was done with an
equality test.

This anchored a couple of things firmly in my mind: that == is
sometimes what you want to test floating point numbers for, and that
floats are exact. There was no error in the end points of the
intervals. They were exact values even though, in most cases, neither
was an entirely accurate representation of the value the programmer
wanted.
 
B

Ben Bacarisse

Mark McIntyre said:
No, you're incorrect there. The value is stored in a representation
which may, or may not, be capable of storing the value 1 exactly, but
the C standard doesn't require it to.

I think it does. A decimal constant must be converted to the nearest
representable value (6.4.4.2 p3), and FLT_RADIX must be an integer
constant (5.2.4.2.2 p1). When the floating point radix is integral,
1.0 is always representable.
It so happens that if stored in binary the value can be stored
exactly, but other coding schemes are allowable by the C standard.


Actually, the boot is on the other foot: you'd need to find a quote
that required the FP implementation to store integers exactly as
otherwise the C standard imposes no requirements.

5.2.4.2.2 seems to be the key as far as representing integers is
concerned. There are other factors of course (floating constants --
see above) and conversions like double x = 1; (6.3.1.4 p2) but they
all come down the same way.
 
K

Keith Thompson

Mark McIntyre said:
No, you're incorrect there. The value is stored in a representation
which may, or may not, be capable of storing the value 1 exactly, but
the C standard doesn't require it to.

I believe it does. Take a look at C99 5.2.4.2.2, particularly
paragraphs 1 and 2. It defines a (fairly loose parameterized) model
for floating-point types. I think that any floating-point
representation that satisfies that model with the minimum
characteristics given later in that subsection must be able to
represent 1.0 exactly.

[...]
 
B

Ben Bacarisse

Mark McIntyre said:
6.4.4.2(3)

For decimal floating constants, and also for hexadecimal floating
constants when FLT_RADIX is not a power of 2, the result is either the
nearest representable value, or the larger or smaller representable
value immediately adjacent to the nearest representable value, chosen
in an implementation-defined manner.

Since the FLT_RADIX need not be a power of 2, it is implementation
defined whether a given value can be stored precisely or not.

But is must be an integer. That makes, for example, 1 a number that
is always representable in all conforming C implementations (there are
some other details but they all fall into place).
 
C

CBFalconer

Keith said:
.... snip ...


A floating point value makes no assertion at all. It can be
interpreted in any of several ways, depending on the context. Your
assertion that a given value represents a range is no better founded
than an assertion that it represents one specific value.

Given:
double x = 1.0;
the value of x is exactly 1.0, no more, no less. What that value
*means*, whether it's just that specific value or any arbitrary value
in some specified range, depends on the application.

I maintain that your example is using 'other facts, such as overall
program structure'. I am talking about what the user can get by
examining the contents of the object x.
 
C

CBFalconer

Richard said:
CBFalconer said:
.... snip ...


Values don't make assertions. Values just *are*. How we interpret
them is our business, not theirs.

<snip - and yes, I did read the bit I snipped, and no, I don't think
it's even remotely relevant. In fact, I think it's gibberish.>

Well, since you seem happy processing gibberish, I will restore the
missing quote for the benefit of other readers.
 
E

Eric Sosman

Mark said:
Mark said:
On 21/04/09 11:18, Alessio Ribeca wrote:

Thank you, How can I check for [floating-point] equality ?

You can't. You can only see if two floats are very close to each other.

This bit of nonsense has cropped up more than once in this
thread, so I'm very much afraid people may believe it. But it's
still nonsense!

I disagree.
The C language *is* capable of testing for equality of two
floating-point values, using the `==' operator. Applied to two
identical values it will produce the result 1 (true);

This a true but useless fact.

So your "you can't" is ... what? An untrue fact?
Seems to me that an untrue fact qualifies as "nonsense."
Its like stating that flipping a coin is
guaranteed to turn up heads. Sure, its likely to happen - but it might
take forever.

Your analogy is like comparing a flapjack to a furbelow.
And in my view its dangerous to state this because a noob reading your
post might stop here and go away thinking that the == operator can be
usefully used on floats.

And a noob reading *your* post might go away thinking that
the `==' operator could not be used on floating-point numbers.
Why? Because you said it could not be done, flat-out. You
were wrong, flat-out -- and now you're both admitting it and
trying to pretend you were right, at the very same time. Have
you considered a career in politics?
And don't listen to anyone who tells you its safe to use == to compare
floats. Really Eric, I'm shocked. Is this you, or a sockpuppet.

C'est moi, dunderhead. You have excised (1) my explanation
of why strict equality testing is usually inadvisable, (2) my
explication of two count them two kinds of tests that are often
more useful, (3) my cautions about the fallacies of treating
"close enough" as if it were a form of equality, and (4) my
unassailable demonstration that your "you can't" was nonsense.
 
E

Eric Sosman

Eric said:
[... in anger and in haste ...]

Mark, I apologize for the tone of my rejoinder. There
was no call for me to stoop to such viciousness when a
simple "you're wrong" would have sufficed. I'm sorry.
 
B

Barry Schwarz

Because floating point values are not exact. They always simply
assert they mean a value between V (the value printed) - x_EPSILON
and V + x_EPSILON. Replace x by FLOAT or DOUBLE, depending on type
used. The EPSILON values are found in float.h.

Actually, you replace the x by FLT or DBL or LDBL.

But this is still incorrect for values that are not near 1.0 While
the expression
(1.0+DBL_EPSILON == 1.0)
is guaranteed to evaluate to 0, the same cannot be said for the
expression
(1.0e23+DBL_EPSILON == 1.0e23)
which on most system will evaluate to 1.
 
C

CBFalconer

Phil said:
.... snip ...


No C variable or value makes any assertions about anything at all.

Yes they do. ints can represent all integers, between INT_MAX and
INT_MIN. chars can represent a smaller range of integers, which
are alleged to be sufficient to describe the available char set.
floats represent a subset of the reals, which subset is also a
subset of the rationals. They cannot represent some values which
are described by the use of x_EPSILON, where x describes the
floating format. These are fundamental assumptions and I don't
believe they are all spelled out in the C standard.
Are C integers exact?
Yes.


What's four divided by three?

In what representation? Several possible C answers are:

1
1.3
1.33
...
1.3333333
4/3

Note that none of those are equal to another. Also note that it is
quite easy to build a rational representation, with some
limitations on ranges of numerators and denominators. One is:

typedef struct rat {
int numerator;
int denominator;
} rational;

Much of the time you don't really need to worry about such things.
But you should be aware of them, so you can figure out what went
wrong.
 
C

CBFalconer

user923005 said:
.... snip ...

On the other hand, the values that are representible in floating
point tend to be useful in practice.

And a number system that could actually store all true floating
point values would be "rather bulky."

I'm glad you didn't try to push it to the reals. Even so, I have
serious doubts as to the feasibility. :)
 
C

CBFalconer

Richard said:
.... snip ...

So what? If the exponent is 0, the value of FLT_RADIX is certainly
irrelevant for 0 and 1 at the very least, so those are two solid
portable examples of numbers that can be represented exactly by
floating point values.

I don't think anyone has said that there are not numbers that can
be stored exactly in a floating point object. What has been said
is that a number in a floating point object never represents an
exact number, rather it represents a range of numbers. Holding the
value closer than that requires further knowledge, which is not
encapsulated in the FP value.

There is a subtle difference between storing and reading.
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top