Machine epsilon: conclusion

R

Richard Heathfield

Harald van D?k said:
The C99 rationale section 7.1.2 gives an example of how it can, and
there is nothing whatsoever in the standard that contradicts it.

I think you're confusing the physical implementation of the header (as
some kind of file) with the concept of "standard header", the
implementation of which is neither here nor there, as the Standard
makes very clear. A standard header *MUST NOT* contain a definition of
QFLT_EPSILON. How the implementation deals with this is up to it.

I presume (not having any way to check it right now) that Mr Navia's
claim (that setting a switch in his compiler renders <float.h> a
standard header) is a correct claim. If so, presumably it does so by
removing the definition of QFLT_EPSILON from <float.h>, possibly by
some kind of #ifdef construct. Were he not to do this, <float.h> would
not be a standard header. Therefore, his implementation agrees with me
and with the Standard that QFLT_EPSILON must not be defined in a
standard header. So he is arguing against his own implementation.
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Richard said:
Harald van D?k said:


I think you're confusing the physical implementation of the header (as
some kind of file) with the concept of "standard header", the
implementation of which is neither here nor there, as the Standard
makes very clear. A standard header *MUST NOT* contain a definition of
QFLT_EPSILON. How the implementation deals with this is up to it.

I'll admit this can be interpreted differently, but I believe <float.h> is a
standard header (using the standard's definition), regardless of whether
the compiler is invoked in a conforming mode. The effect of a standard
header on a nonstandard implementation is outside of the scope of the
standard, but that doesn't make the header nonstandard.
 
F

Flash Gordon

Richard Heathfield wrote, On 30/06/07 20:51:
jacob navia said:


You don't seem to understand my point, which is that you are describing
<float.h> as a *standard header*, and yet you *also* describe it as
containing QFLT_EPSILON. It can't *both* be a standard header *and*
contain QFLT_EPSILON at the same time. If it is a standard header, it
does not contain QFLT_EPSILON. If it contains QFLT_EPSILON, it is not a
standard header. Your claim that QFLT_EPSILON is in a standard header
is simply wrong, switch or no switch.

Well, if it was appropriately guarded it *could* be there. E.g.

#define FLT_EPSILON 1.19209290e-07F // float
#define DBL_EPSILON 2.2204460492503131e-16 // double
#define LDBL_EPSILON 1.084202172485504434007452e-19L //long double
#ifdef _LCCWIN_EXTENSIONS
// qfloat epsilon truncated so that it fits in this page...
# define QFLT_EPSILON 1.09003771904865842969737513593110651 ... E-106
#endif

However, that is not how Jacob is presenting it.
 
K

Keith Thompson

Not all C implementations use these specific values for FLT_EPSILON,
DBL_EPSILON, and LDBL_EPSILON. For example, I've worked on a system
where both float and double are 64 bits with a 13-bit exponent
(non-IEEE). You should make it clear that those values are specific
to IEC 60559 implementations -- though even on such systems, Annex F
allows some flexibility in the representation of long double.

But you don't mention it in your tutorial.
The compiler you use has a file called
"math.h"

Quibble: his *implementation" has such a file; it's not part of the
compiler.
There, I can read

# define M_E 2.7182818284590452354 /* e */ [...]
# define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */

but that doesn't bother you since when you call that compiler
with the needed flags, those definitions do not appear.
Correct.

When I do exactly the same you will argue without end.

He's not complaining about the behavior of your compiler. If
lcc-win32, with the "-ansic" option, disables the definition of
QFLT_EPSILON in <float.h>, that's great; your compiler is doing
exactly the right thing.

He's complaining about the contents of your tutorial, in which you
present QFLT_EPSILON as part of the <float.h> header. If you were to
make it clear in your tutorial that <float.h> only defines
QFLT_EPSILON when lcc-win32 is invoked in a non-conforming mode, I
think that would address his complaint.

The suggestion that such extensions should be in separate headers is
also a good one, but I suppose making such a change would break
existing code that depends on the way lcc-win32 has already
implemented these extensions. You might keep it in mind when you add
other extension to your implementation in the future, though.

Personally, I think your tutorial should make a much clearer
distinction between what's defined by the ISO C standard and what's
defined only by a particular implementation. I'd probably put all
implementation-specific information in an appendix, with brief
references at the relevant points of the tutorial. Something like:

<float.h> defines FLT_EPSILON, DBL_EPSILON, and LDBL_EPSILON as
follows: ... [See Appendix A section 42 for information about
lcc-win32 extensions in <float.h>.]

I believe such a structure would be much more useful if your target
audience is programmers who are interested in standard C.

If that's *not* your target audience, then I suggest you should be
having this discussion in comp.compilers.lcc.
The fact that my compiler is the only C compiler giving to the user
105 digits floating point precision is not important to you.

It's not important to me either. I don't say that to be insulting.
I'm sure it's useful to some people. I just don't happen to do C
programming under Win32.
Polemic, polemic without end, but you did not contribute anything
to this discussion.

He's contributed a great deal.
 
M

Mark McIntyre

Richard Tobin said:


Either it's a standard header (as he claims), or it isn't. If it's a
standard header, it cannot contain QFLT_EPSILON. If it contains
QFLT_EPSILON, it can't be a standard header.

This is untrue. A header can contain any extraneous material it likes,
as long as *when invoked in conforming mode* the compiler does not
pick up this material.

In any events your argument is specious: Pretty much every compiler
writer includes nonstandard stuff in their headers, and protects it
via conditionals etc.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
M

Mark McIntyre

Polemic, polemic without end, but you did not contribute anything
to this discussion.

Jacob, in this instance I agree with you but I also recommend you
ignore Richard, he's being stupid. He was wrong earlier in this
thread, and he's now doing _exactly_ what he frequently complains
about others doing, viz changing his argument to cover his tracks
instead of admitting his error.

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
J

Joe Wright

jacob said:
Eric said:
jacob said:
Following the discussion about the machine epsilon, I have modified the
text as follows. I thank all people that contributed. It was
interesting, and I surely learned stuff I did not consider before.
--------------------------------------------------------------
The machine epsilon
-------------------
The standard defines for each floating point representation (float,
double, long double) the difference between 1 and the least value
greater than 1 that is representable in the given floating point
type. In IEEE754 representation this number has an exponent value of
the bias, and a fraction of 1. [...]

It's been mentioned before, but what do you mean by "the bias?"
If you mean the offset added to the exponent's numerical value to
produce the encoded value, that's wrong. If you mean something
else, it would be as well to explain what you mean.

You are right again. Actually, the bias is 1023, and the value is
971.

#include <stdio.h>
#include <float.h>
int main(void)
{
double d = DBL_EPSILON;
int *p = (int *)&d;

printf("%a\n",DBL_EPSILON);
printf("0x%x 0x%x\n",p[0],p[1]);
}
0x1.000000p-52
0x0 0x3cb00000
3cb == 971
971-1023 --> -52
2 ^-52 --> 2.2204460492503130808472633361816e-16 -->DBL_EPSILON.

Similar calculations can be done for the other types. I will correct
this.

Consider please..

00111100 10110000 00000000 00000000 00000000 00000000 00000000 00000000
Exp = 971 (-51)
111 11001101
Man = .10000 00000000 00000000 00000000 00000000 00000000 00000000
2.2204460492503131e-16

I see the mantissa as a fraction (less than 1). For this reason the bias
applied to the exponent is 2022. How do you justify the decimal
precision that you show? The above printf representation is "%.16e" and
will give you all the precision there is in a double.
 
R

Richard Tobin

Jacon already described how to suppress this definition if required.
[/QUOTE]
Either it's a standard header (as he claims), or it isn't.

It's a standard header when -ansic is specified, and a non-standard
one when it isn't. There's no requirement on the file representation
of standard headers, only on what they define (by the as-if rule if
nothing else).

-- Richard
 
R

Richard Tobin

I'm not convinced about this. Using a leading underscore on names
intended for the user (rather than the implementation) is not helpful
to the user who wants to use the extensions. We don't see Posix using
underscored identifiers for everything.
[/QUOTE]
Most Unix extensions are not in the C standard headers, rather they are
provided in additional headers.

I don't know about "most", but on the machine I'm using there are
(conditionalised) Posix definitions in stdio.h, stdlib.h, and
string.h, which were the first three headers that came to mind.
Here you are suggesting using a leading underscore for a name intended
for the user ;-)

I'm suggesting *one*, so that the others don't have to be.

-- Richard
 
R

Richard Tobin

00111100 10110000 00000000 00000000 00000000 00000000 00000000 00000000
Exp = 971 (-51)

???

111100 1011
this is 971 (3CB). Minus the bias (1023) gives -52, not -51[/QUOTE]

You can consider the mantissa as between 1 and 2, and the exponent as
-52, or take the mantissa as between 0.5 and 1, and exponent as -51.
It comes to the same thing, you just have to be clear which convention
you are using.

-- Richard
 
J

jacob navia

Joe said:
Consider please..

00111100 10110000 00000000 00000000 00000000 00000000 00000000 00000000
Exp = 971 (-51)

???

111100 1011
this is 971 (3CB). Minus the bias (1023) gives -52, not -51
You can read this in
http://en.wikipedia.org/wiki/Exponent_bias:
When interpreting the floating-point number, the bias is subtracted to
retrieve the actual exponent.
[snip]
For a double-precision number, an exponent in the range −1022 .. +1023
is biased by adding 1023 to get a value in the range 1 .. 2046 (0 and
2047 have special meanings).

I repeat: 971-1023--> -52, not -51.
111 11001101
Man = .10000 00000000 00000000 00000000 00000000 00000000 00000000
2.2204460492503131e-16

I see the mantissa as a fraction (less than 1). For this reason the bias
applied to the exponent is 2022.
??? 2022 ???
That is wrong.
How do you justify the decimal
precision that you show? The above printf representation is "%.16e" and
will give you all the precision there is in a double.

Correct. I just calculated 2^-52 with my calculator and pasted the
result here. Double precision just gives you 16 digits.
 
K

Keith Thompson

Most Unix extensions are not in the C standard headers, rather they are
provided in additional headers.

I don't know about "most", but on the machine I'm using there are
(conditionalised) Posix definitions in stdio.h, stdlib.h, and
string.h, which were the first three headers that came to mind.
Here you are suggesting using a leading underscore for a name intended
for the user ;-)

I'm suggesting *one*, so that the others don't have to be.[/QUOTE]

In the particular case of qfloat, preprocessor magic isn't even
necessary. The compiler could have a predefined type __qfloat, and a
<qfloat.h> header could look something like this:

#ifndef __QFLOAT_H
#define __QFLOAT_H

typedef __qfloat qfloat;
#define QFLT_EPSILON /* whatever */
/* and so on */
#endif

This would have no effect on any portable code; code that wants to use
qfloat can simply have a "#include <qfloat.h>".

The point is that it's entirely possible to implement *some*
extensions without the need for a non-conforming mode; just provide a
header.
 
F

Flash Gordon

Richard Tobin wrote, On 30/06/07 22:42:
Most Unix extensions are not in the C standard headers, rather they are
provided in additional headers.

I don't know about "most", but on the machine I'm using there are
(conditionalised) Posix definitions in stdio.h, stdlib.h, and
string.h, which were the first three headers that came to mind.[/QUOTE]

<weasel>
I was thinking of all the headers starting sys/
</weasel>

I'll accept I might be wrong here.
I'm suggesting *one*, so that the others don't have to be.

The comment was not serious. I actually agree that this was a sensible
suggestion.
 
R

Richard Heathfield

Harald van D?k said:
Richard Heathfield wrote:


I'll admit this can be interpreted differently, but I believe
<float.h> is a standard header (using the standard's definition),
regardless of whether the compiler is invoked in a conforming mode.

If the compiler is not invoked in a conforming mode, it is not bound by
the Standard, in which case all bets are off, and the discussion is no
longer topical.
The effect of a standard header on a nonstandard implementation is
outside of the scope of the standard, but that doesn't make the header
nonstandard.

If the implementation is non-standard, the concept of a "standard
header" no longer carries useful meaning.
 
R

Richard Heathfield

Flash Gordon said:
Richard Heathfield wrote, On 30/06/07 20:51:


Well, if it was appropriately guarded it *could* be there. E.g.
#ifdef _LCCWIN_EXTENSIONS
// qfloat epsilon truncated so that it fits in this page...
# define QFLT_EPSILON 1.09003771904865842969737513593110651 ... E-106
#endif

Nobody is claiming that those lines of code can't be in some kind of
underlying "physical" representation of <float.h>, but the #define
can't appear in any standard header. The #ifdef is a reasonable
mechanism for preventing this, and that's presumably pretty much how
lcc-win32 does it (although I haven't actually looked).
However, that is not how Jacob is presenting it.

Right. The way his tutorial presents it, an intelligent but ignorant
reader can reasonably draw the conclusion that QFLT_EPSILON is part of
a standard <float.h> header. And that would be a false conclusion,
correctly drawn from a false premise (i.e. the premise that the
tutorial is correct).
 
R

Richard Heathfield

Richard Tobin said:
Either it's a standard header (as he claims), or it isn't.

It's a standard header when -ansic is specified, and a non-standard
one when it isn't.[/QUOTE]

Exactly right. Now look at the OP:

+++ Begin quote +++
For the different representations we have in the standard header
<float.h>:

#define FLT_EPSILON 1.19209290e-07F // float
#define DBL_EPSILON 2.2204460492503131e-16 // double
#define LDBL_EPSILON 1.084202172485504434007452e-19L //long double
// qfloat epsilon truncated so that it fits in this page...
#define QFLT_EPSILON 1.09003771904865842969737513593110651 ... E-106

+++ End quote +++

Note that he is claiming that this text appears in the ***standard
header*** <float.h>, but if his standard-conforming switch is set, it
mustn't appear in the standard header.
 
J

jacob navia

Richard said:
Richard Tobin said:


Exactly right. Now look at the OP:

+++ Begin quote +++
For the different representations we have in the standard header
<float.h>:

#define FLT_EPSILON 1.19209290e-07F // float
#define DBL_EPSILON 2.2204460492503131e-16 // double
#define LDBL_EPSILON 1.084202172485504434007452e-19L //long double
// qfloat epsilon truncated so that it fits in this page...
#define QFLT_EPSILON 1.09003771904865842969737513593110651 ... E-106

+++ End quote +++

The next sentence, just below but not quoted by mr heathfield reads:

These definitions (except the qfloat part) are part of the C99 ANSI
standard. For the standard types (float, double and long double) they
should always exist in other compilers.
Note that he is claiming that this text appears in the ***standard
header*** <float.h>, but if his standard-conforming switch is set, it
mustn't appear in the standard header.
It is guarded by ifdefs, as I have explained thousand times.
I do not see the need to quote the ifdefs, since I say in the text that
the qfloat part is not part of the standard.

But this is hopeless, and I will not go on this sub-thread.
 
R

Richard Heathfield

jacob navia said:
The next sentence, just below but not quoted by mr heathfield reads:

These definitions (except the qfloat part) are part of the C99 ANSI
standard. For the standard types (float, double and long double) they
should always exist in other compilers.

You still don't get it, do you? Look, if I wrote a tutorial on - oh,
let's make it something non-C-ish... okay, Chess. I'm no chess expert,
so obviously I'm well-placed to write a chess tutorial. If I wrote
this:

+++ Richard's Broken Chess Guide +++
In a standard chess game, each player has eight pawns, and ten pieces:
two rooks, two knights, two bishops, two frigates, one queen and one
king.

These pieces, except for the frigates, are part of a standard chess
game.
+++ end +++

then a competent chess player would be perfectly right to complain that
the first of those two paragraphs is wrong, despite the presence of the
second paragraph.

Well, this is exactly the same thing. Your first bit is wrong. The fact
that you have a second bit is irrelevant. The first bit is still wrong.
But this is hopeless,

Yes, I know.
and I will not go on this sub-thread.

Really?
 
F

Flash Gordon

jacob navia wrote, On 30/06/07 23:42:
It is guarded by ifdefs, as I have explained thousand times.

As you've been told a million times, don't exaggerate.

In any case, this is about your tutorial which clearly does not explain
it a thousand times.
I do not see the need to quote the ifdefs, since I say in the text that
the qfloat part is not part of the standard.

IMHO your tutorial would be clearer if you did show the guards. One of
many things that you should realise when writing a tutorial is that a
piece of information only presented once will in all probability not be
taken in by a significant portion of your audience. Also some of those
using your tutorial and compiler will probably then look at the header
and be puzzled by the difference.

You should also mention clearly that other values are used in other
implementations.
But this is hopeless, and I will not go on this sub-thread.

Fine.
 

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
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top