A
Antoninus Twink
Dumb Chucky
Chucking hell, that's a great one - I'll have to remember it for future
use.
CBF... the Dumb Chuck.
Dumb Chucky
Keith said:.... snip ...
To be clear, a and b are PRN objects, and A and B are real values,
yes? And those real values are not exactly representable as PRNs
(there are no PRN values whose corresponding real values exactly
match A and B). Therefore it is simply not possible to store A
in a, or B in b. Only a PRN value can be stored in a PRN object.
What you can do, of course, is store a *close approximation* of
a given real value in a PRN object. Thus we can store the PRN
value ap in the PRN object a, and the PRN value bp in in the PRN
object b. Each of these PRN values has a unique corresponding
real value; call them apr and bpr if you like.
Ike Naar said:Just out of curiosity I tried that on my desktop (x86/OpenBSD/gcc+glibc).
Floatingpoint type used is float.
fpav = 1.5
fpav is exactly representable as a float, with bit pattern 0x3fc00000
FLT_EPSILON = 0.00000011920928955078125
The range for fpav, the way you define it,
is fpav*(1-FLT_EPSILON) through fpav*(1+FLT_EPSILON)
is 1.5 * 0.99999988079071044921875 through 1.5 * 1.00000011920928955078125
is 1.499999821186065673828125 through 1.500000178813934326171875
This "range" has an unexpected feature:
prev(fpav), the previous representable float smaller than fpav,
has bit pattern 0x3fbfffff and value 1.49999988079071044921875
next(fpav), the next representable float larger than fpav,
has bit pattern 0x3fc00001 and value 1.50000011920928955078125
Keith said:.... snip ...
Yes, I am looking at the value of the fp object. Are you now
acknowledging that there is such a thing, and that it's a real
value, not a range?
Your concept of "what the value represents" is not something
that exists in a C program or is defined by the C standard.
Right. To know what the value represents, all you have to do is
make something up.
Keith said:.... snip ...
Was that intended as a correction? Your statement is true, but
it's a very different statement from the one Flash made. Flash's
statement is also true.
Between two consecutive floating-point numbers, there are
infinitely many real values. Between two consecutive floating-
point numbers, there are no other floating-point numbers (by
definition of the word "consecutive").
CBFalconer said:I was simply trying to clear up the confused use of 'floating point
number'.
Ike said:Just out of curiosity I tried that on my desktop
(x86/OpenBSD/gcc+glibc). Floatingpoint type used is float.
fpav = 1.5
fpav is exactly representable as a float, with bit pattern 0x3fc00000
FLT_EPSILON = 0.00000011920928955078125
The range for fpav, the way you define it,
is fpav*(1-FLT_EPSILON) through fpav*(1+FLT_EPSILON)
is 1.5 * 0.99999988079071044921875 through 1.5 * 1.00000011920928955078125
is 1.499999821186065673828125 through 1.500000178813934326171875
This "range" has an unexpected feature:
prev(fpav), the previous representable float smaller than fpav,
has bit pattern 0x3fbfffff and value 1.49999988079071044921875
next(fpav), the next representable float larger than fpav,
has bit pattern 0x3fc00001 and value 1.50000011920928955078125
That means that prev(fpav) and next(fpav) are well inside fpav's range!
fpav's range, as defined by you, contains three representable floats:
prev(fpav), fpav itself, and next(fpav).
CBFalconer said:I think the introduction of PRNs has simply complicated the
argument. You are busy denying that fp values represent a range,
while I insist that they do. We also have a problem with what to
call an FP value - one option is the number in the FP object (which
is exact), and another is what numbers that thing can represent,
which is a range of values. We hang the 'value' stamp on both.
I am always considering the fp object in isolation - i.e. there is
no examination of the code that created a value to store in it.
I maintain that your PRN description omits some of the fundamentals
of fp descriptions, and that the result is unusable. This is tied
into the actual 'ranges' implied in fp values, in that no real
value can belong to more that one fp 'range'. An fp 'range' is the
range associated with an fp exact value.
I am clear in my own mind about what I am talking about. I may not
be expressing it in a suitable manner to impress others.
[snip]Consider one process of generating a fp object.
When we are done, we have the final fp value. Now the
question is 'what does this represent'.
I maintain the best possible answer is that it represents some
value in the fp 'range' associated with that fp value. It may be
worse, but it can't be better known.
Keith said:.... 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.
CBFalconer said:Keith said:... 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
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.
William Pursell said:There are many different reasonable interpretations of the
value stored. One reasonable interpretation is that the stored
value is a representative of an interval in the reals. However,
that is NOT the only reasonable interpretation, and it is
certainly not an interpretation that is mandated by the
C standard.
This means that my definition was flawed. As you can see, the flaw
is not very large.
You will find other confusions by looking at
the range of 1.0, because the hex representation will change as the
value becomes smaller than 1.0.
Keith said:There was nothing confused about it.
and your double object can be representing anything fom
42*(1-DBL_EPSILON) though 42*(1+DBL_EPSILON). (typical). Without
detailed examination of the code you can't tell anything more. The
standard specifies the makeup of a fp value in terms of
significand, sign, and exponent. That forces all the 'ranges' to
consist of 'touching' real values, and ensures that no real value
can belong to more than one 'range'. That is the magic that
enables the sensible use of <, >, <=, >= conditions, but not ==.
Yes, I am creating another critical name, 'touching'.
Note that a 'range' consists of real values, and any interval of
real values contains an infinite number of values. There is only
one value of the fp object, so the odds of its accuracy are
negligible. This has nothing to do with the C standard, but with
mathematics.
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?
The "value represented" and the "number stored" are the same thing.
What you're referring to as the "number stored", if I understand you
correctly, does not exist. Given:
double frac = 1.0 / 3.0;
I think you're saying that the "number stored" is the real value
one-third.
Keith said:CBFalconer said:Keith said:... 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.)
You've seized on these constants and assumed that they have some
deep significance in the meaning of all floating-point values.
They really aren't that fundamental. They're just the difference
between 1.0 and the smallest floating-point number greater than
1.0.
1.0 is representable in type double. 1.0+DBL_EPSILON is representable
in type double. There are no values of type double between those two
values.
double x = 1.0;
double y = 1.0 + DBL_EPSILON;
There really is a gap between the values of x and y, and x and y do
not have "ranges" that fill in that gap. An object of type double can
only represent one of a relatively few distinct values. Real values
between those distinct values are simply not covered. (Perhaps that's
the idea that you're unable to accept.)
In fact, the *_EPSILON values can be derived from the model of
floating-point numbers given in the first two paragraphs of 5.2.4.2.2,
along with the values of b, emin, emax, and p. If your idea about
"ranges" can be derived from the description of *_EPSILON, you should
be able to derive it from the model.
[...]
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?
The "value represented" and the "number stored" are the same thing.
What you're referring to as the "number stored", if I understand you
correctly, does not exist. Given:
double frac = 1.0 / 3.0;
I think you're saying that the "number stored" is the real value
one-third. That value never exists during the compilation or
execution of the C program. The value that does exist is a rational
number, a multiple of a power of 2.0 (or, more generally, of
FLT_RADIX) that is a close approximation of one-third. And that is
the value represented by frac after it's been initialized, and it's
the value you'll see if you examine the object later.
Keith said:It is, in fact, an interpretation that is flatly contradicted by
the C standard.
Flash said:CBFalconer wrote:
Given two numbers x and y whose values are "touching ranges" with
y being the next greater range than x then in your model we have:
x represents xmin to xmax
y represents ymin to ymax
x < y
xmax equal to ymin (there can be no intervening real numbers since
if there were any there would be an infinite number)
Flash said:I agree completely with what Keith has stated in this sub-thread.
I believe I was entirely consistent about using real to refer to
the set in maths known as reals and floating point to refer to
numbers in a floating point number system (i.e. one where there
is a finite limit on the number of digits and a method of
specifying the position of the "point" (which could be a decimal
point, a binary point, or a point in any other number base)
relative to the to the position of those digits within a finite
range of positions. I.e., I used "floating point number" to refer
to what is commonly called "floating point number" and "real" for
what is commonly called "real".
Keith's paraphrase of what I said is accurate. It only mentions
the special case (where I gave the general), but that special
case is the important one. Nothing important was lost in the
rephrasing and the terminology was unchanged.
Ike said:In this particular case, your range was 1.5 times too wide. For
numbers slightly smaller than a power of 2, your ranges are
almost two times too wide.
For me this whole "range" idea makes little sense. Suppose you
manage to provide a proper definition for the range, what can you
do with it that you can't do without?
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.