Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

FLT_EPSILON > 5.42101e-20

137 views
Skip to first unread message

Dariusz Linda

unread,
Jul 9, 2009, 1:51:59 PM7/9/09
to
Hi!
Can anyone tell me please, why FLT_EPSILON, wchich is 1.19209290e-07
in MSVC and GCC, is actually NOT the smallest value such that 1.0 +
FLT_EPSILON != 1.0. A simple computation:
float eps = 1.0;
while (eps + 1.0 != 1.0) eps *= 0.5;
shows that it's value should be 5.42101e-20.

thanks
D.L.
--
comp.lang.c.moderated - moderation address: cl...@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.

Jean-Marc Bourguet

unread,
Jul 13, 2009, 3:32:47 AM7/13/09
to
Dariusz Linda <darius...@gmail.com> writes:

> Hi!
> Can anyone tell me please, why FLT_EPSILON, wchich is 1.19209290e-07
> in MSVC and GCC, is actually NOT the smallest value such that 1.0 +
> FLT_EPSILON != 1.0. A simple computation:
> float eps = 1.0;
> while (eps + 1.0 != 1.0) eps *= 0.5;
> shows that it's value should be 5.42101e-20.

Three reasons:

1/ there is a promotion to double in the expressions you are giving,

2/ C standard allows for intermediate computations to be done in a more
precise type than their static type

3/ rounding can also account for a factor 2 (the true definition is "the
difference between 1 and the next representable floating point number",
which doesn't depend on rounding).

Yours,

--
Jean-Marc

Keith Thompson

unread,
Jul 13, 2009, 3:33:03 AM7/13/09
to
Dariusz Linda <darius...@gmail.com> writes:
> Can anyone tell me please, why FLT_EPSILON, wchich is 1.19209290e-07
> in MSVC and GCC, is actually NOT the smallest value such that 1.0 +
> FLT_EPSILON != 1.0. A simple computation:
> float eps = 1.0;
> while (eps + 1.0 != 1.0) eps *= 0.5;
> shows that it's value should be 5.42101e-20.

For one thing, that's not how FLT_EPSILON is defined. See C99
5.2.4.2.2p10. It's "the difference between 1 and the least value
greater than 1 that is representable in the given floating point
type". (K&R2 gets this wrong, or at least disagrees with the
standard.)

For another, the expressions ``eps + 1.0'' and ``1.0'' are of type
double, not float. And even if you replace 1.0 by 1.0f, the
implementation is permitted to evaluate intermediate expressions in
greater precision.

You can avoid this by storing the result of ``eps + 1.0'' in an object
before comparing it, but when I tried this I still got a result that
was off by a factor of 2 due to rounding issues.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Hans-Bernhard Bröker

unread,
Jul 13, 2009, 3:33:24 AM7/13/09
to
Dariusz Linda wrote:

> Can anyone tell me please, why FLT_EPSILON, wchich is 1.19209290e-07
> in MSVC and GCC, is actually NOT the smallest value such that 1.0 +
> FLT_EPSILON != 1.0.

Ultimately because that's the definition of DBL_EPSILON, not FLT_EPSILON
you're quoting. The definition of FLT_EPSILON would have a formula like

(float)(1.0f + FLT_EPSILON) != 1.0f

in it.

> float eps = 1.0;
> while (eps + 1.0 != 1.0) eps *= 0.5;
> shows that it's value should be 5.42101e-20.

No. That computes DBL_EPSILON if you're lucky. The result suggests
you're not.

Barry Schwarz

unread,
Jul 13, 2009, 3:34:19 AM7/13/09
to
On Thu, 9 Jul 2009 12:51:59 -0500 (CDT), Dariusz Linda
<darius...@gmail.com> wrote:

>Hi!
>Can anyone tell me please, why FLT_EPSILON, wchich is 1.19209290e-07
>in MSVC and GCC, is actually NOT the smallest value such that 1.0 +
>FLT_EPSILON != 1.0. A simple computation:
>float eps = 1.0;
>while (eps + 1.0 != 1.0) eps *= 0.5;

Everything is converted to doubles. If you want to perform float
arithmetic, use 1.0f etc.

>shows that it's value should be 5.42101e-20.
>
>thanks
>D.L.

--
Remove del for email

Alan Curry

unread,
Jul 13, 2009, 3:34:30 AM7/13/09
to
In article <clcm-2009...@plethora.net>,

Dariusz Linda <darius...@gmail.com> wrote:
>Hi!
>Can anyone tell me please, why FLT_EPSILON, wchich is 1.19209290e-07
>in MSVC and GCC, is actually NOT the smallest value such that 1.0 +
>FLT_EPSILON != 1.0. A simple computation:
>float eps = 1.0;
>while (eps + 1.0 != 1.0) eps *= 0.5;

1.0 is a double, so your addition and comparison are done as doubles. Change
both instances of 1.0 to 1.0f and try again. eps will end up being half of
FLT_EPSILON, since the value you want is actually the one that was present on
the next-to-last pass through the loop (which passed the "add to 1" test)
rather than the final pass through the loop (which failed the "add to 1"
test).

--
Alan Curry

Jasen Betts

unread,
Jul 13, 2009, 3:34:46 AM7/13/09
to
On 2009-07-09, Dariusz Linda <darius...@gmail.com> wrote:
> Hi!
> Can anyone tell me please, why FLT_EPSILON, wchich is 1.19209290e-07
> in MSVC and GCC, is actually NOT the smallest value such that 1.0 +
> FLT_EPSILON != 1.0. A simple computation:
> float eps = 1.0;
> while (eps + 1.0 != 1.0) eps *= 0.5;
> shows that it's value should be 5.42101e-20.

you're using doubles (or worse) for the computation.

#include <stdio.h>
int main()
{
float a=1;
float b=1;
a+=(1.19209290e-07/2);
printf("a=%f b=%f a-b=%f a=b:%d\n",a,b,a-b,a=b);
return 0;

Thomas Richter

unread,
Jul 13, 2009, 3:35:22 AM7/13/09
to
Dariusz Linda wrote:
> Hi!
> Can anyone tell me please, why FLT_EPSILON, wchich is 1.19209290e-07
> in MSVC and GCC, is actually NOT the smallest value such that 1.0 +
> FLT_EPSILON != 1.0. A simple computation:
> float eps = 1.0;
> while (eps + 1.0 != 1.0) eps *= 0.5;
> shows that it's value should be 5.42101e-20.

Note that 1.0 is a double, not a float, so the expression eps + 1.0 is
evaluated by first converting eps to a double. Instead, you should use:

while (eps + 1.0f != 1.0f) eps *= 0.5;

Greetings,
Thomas

0 new messages