K
Keith Thompson
CBFalconer said:Keith said:CBFalconer said:Keith Thompson wrote:
... snip ...
If an int object i contains the value 42, it doesn't matter
whether it was generated via
int i = 42;
or
int i = 6 * 7;
or
int i = 429 / 10;
The meaning of the stored value 42 is independent of how it was
generated.
If a double object x contains the value 42.0, it doesn't matter
how it was generated. The meaning of 42.0 is independent of how
it was generated.
No, it isn't. To quote the standard again:
5.2.4.2.2:
... snip ...
[#10] The values given in the following list shall be
replaced by implementation-defined constant expressions with
(positive) values that are less than or equal to those
shown:
-- the difference between 1 and the least value greater
than 1 that is representable in the given floating
point type, b1-p
FLT_EPSILON 1E-5
DBL_EPSILON 1E-9
LDBL_EPSILON 1E-9
Yes, yes, we all know what the *_EPSILON constants mean -- and
it's not what you seem to think they mean. FLT_EPSILON has a
very specific meaning, and you've just quoted it.
FLT_EPSILON == nextafter(1.0, 2.0) - 1.0
(See C99 7.12.11.1 for the nextafter() function.)
No, you misunderstand the fundamentals. With the normal fp
implementation, the value 1+EPSILON will not be represented as
1.0. nextafter(1.0, 0.5) will be the first value less than 1.0 not
represented as 1.0. (I was not aware the nextafter function
existed - it makes explanations easier.) That 'range' that is
represented by 1.0 is the fundamental characteristic of the fp
value 1.0. A proper implementation of nextafter will handle the
funny results due to rounding policies, etc.
No, the fundamental characteristic of the floating-point value 1.0 is
the real value 1.0. I'm not missing your point; I just disagree with
it.
If the *_EPSILON constants are so fundamental, why does the standard
place so little emphasis on them?
But you miss the fact that all values greater than 1.0 and less
than 1.0+EPSILON (I am dropping the DBL - it is just a typing
nuisance) are _represented_ by the value 1.0. If you go through
the same process to find the first value less than 1.0 that has a
separate value, you again have a portion of the 'range', i.e. that
portion that is less than 1.0. No matter what you do, using that
fp system, you cannot represent any real value in that 'range' as
anything other than 1.0. The necessary consequence is that when
you read 1.0 you don't know what it represents, other than
something in the 'range'.
No, *you* miss the fact that values greater than 1.0 and less than
1.0+EPSILON *are not represented*. You cannot represent any real
value in the range (1.0, 1.0+EPSILON) *at all*.
Floating-point types are not continuous, they're discrete. The FP
value 1.0 is a close approximation of the real value 1.0+VERY_TINY,
but it isn't 1.0+VERY_TINY, it's just 1.0.
And we can, easily. Look at the hex representation of 1.0. Find
the significand portion. Increment that by one least significant
bit. You have just formed nextafter(1.0, 2.0).
Yes, but that doesn't support your claim about ranges, which is what I
asked.
[...]
There is continuous confusion here from confusing the value
represented by the fp object, and the number stored in the fp
object. They are probably different.
They're *probably* different?
Yes, because there are an infinite number of reals in the 'range',
and only one object value. Ignoring the programming that set the
value, why should you prefer one result to another?
Because only one value in that range is the value of the fp object.
No, you are imposing knowledge of the programming. I am looking
_solely_ at what is stored in the fp object. It can equally well
represent any value in the 'range'. Since there are an infinity of
such values, and only one so-called object value, the probability
that they are identical is extremely small.
No, I am not "imposing knowledge of the programming". I am looking
solely at what is stored in the fp object. I'm just seeing what's
really there, as defined by the C standard.
[...]