can long double be less precise than double? 
Author Message
 can long double be less precise than double?

Hi, i have a problem with using long double:

long double x,y,ymin=0.45,ystep=0.05;

y=0.45+0.05; x = (y>0.5) ? (y-1) : y;
printf("x=%Lf\n",x);
/* this part gives, as expected, x = 0.5 */

y=ymin+ystep; x = (y>0.5) ? (y-1) : y;
printf("x=%Lf\n",x);
/* this part gives x = -0.5 !!!! */

If i change the type from long double to double, i get the expected
result which is 0.5 in both cases.

i simply do not understand what is going on... don't even know where
the problem might be.
(running Linux 2.2.17; processor Pentium III; output of gcc -v  :
  Reading specs from
/usr/lib/gcc-lib/i386-slackware-linux/egcs-2.91.66/specs
  gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
)
thanks in advance,
-amit.
--



Sat, 15 Jan 2005 06:15:51 GMT  
 can long double be less precise than double?

Quote:

> i simply do not understand what is going on... don't even know where
> the problem might be.

The problem is that floating point arithmetic is inherently inaccurate.
If you need to do comparisons between floating point numbers, you should
be doing it with buffering values, e.g., instead of x == y, you should
test abs(x - y) < x*epsilon, with epsilon an appropriately-chosen and
small constant.

--

 __ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/  \ See the son in your bad day / Smell the flowers in the valley
\__/ Chante Moore
    Bosskey.net: Aliens vs. Predator 2 / http://www.bosskey.net/avp2/
 A personal guide to Aliens vs. Predator 2.
--



Sun, 16 Jan 2005 00:51:36 GMT  
 can long double be less precise than double?

comp.lang.c.moderated:

In regards to your the question you asked in the subject line and
neglected to repeat in the body, no.

Quote:
> Hi, i have a problem with using long double:

> long double x,y,ymin=0.45,ystep=0.05;

> y=0.45+0.05; x = (y>0.5) ? (y-1) : y;
> printf("x=%Lf\n",x);
> /* this part gives, as expected, x = 0.5 */
> y=ymin+ystep; x = (y>0.5) ? (y-1) : y;
> printf("x=%Lf\n",x);
> /* this part gives x = -0.5 !!!! */
> If i change the type from long double to double, i get the expected
> result which is 0.5 in both cases.

> i simply do not understand what is going on... don't even know where
> the problem might be.
> (running Linux 2.2.17; processor Pentium III; output of gcc -v  :
>   Reading specs from
> /usr/lib/gcc-lib/i386-slackware-linux/egcs-2.91.66/specs
>   gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
> )
> thanks in advance,
> -amit.

What makes you think this has anything to do with precision?  It has
to do with rounding of floating point types.  Any elementary treatment
of floating point calculations on digital computers should clear it
up.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
--



Sun, 16 Jan 2005 00:52:08 GMT  
 can long double be less precise than double?

Quote:
>long double x,y,ymin=0.45,ystep=0.05;
>y=0.45+0.05; x = (y>0.5) ? (y-1) : y;

0.45 and 0.05 are not representable exactly as binary fractions.
In infinite precision y would be 0.5, hence (y>0.5) would be false,
but in finite precision y picks up 3 roundoff errors, whose net sign
depends on the fraction length.

Note also that your constants 0.45 and 0.05 are double, not long
double.  What's the syntax already?  0.45L ?   Hmmm, your code
might actually guarantee y==0.5 if you take care to use long
double constants, but it would be a really tricky case.
--



Sun, 16 Jan 2005 00:52:16 GMT  
 can long double be less precise than double?

Quote:
> Hi, i have a problem with using long double:

> long double x,y,ymin=0.45,ystep=0.05;

Under the windows OS and using the lcc-win32 compiler I see:
 ymin +4.50000000000000011e-0001
 ystep +5.00000000000000030e-0002

Why?

Because YOU FORGOT THE 'L' AFTER THE CONSTANTS!!!!!!
You should have written:

Quote:
> long double x,y,ymin=0.45L,ystep=0.05L;

If you do NOT write the L the compiler reads a double precision constant and
then converts it to long double precision. The bits 53-63 of the mantissa
are now RANDOM RUBBISH!
--



Sun, 16 Jan 2005 00:52:24 GMT  
 can long double be less precise than double?

Quote:

> Hi, i have a problem with using long double:
> long double x,y,ymin=0.45,ystep=0.05;
> y=0.45+0.05; x = (y>0.5) ? (y-1) : y;
> printf("x=%Lf\n",x);
> /* this part gives, as expected, x = 0.5 */

If this is what you expect, your expectation is at least slightly incorrect.
As the saying goes:

        In computing, 10.0 times 0.1 is hardly ever 1.0

Or, to put the same warning in different words:

        *Never* trust the last digit of any floating point result.

You assume that the result of the computation of y is exactly
0.5000000... to the very last representable digit, and since that
violates the above rule, your expecatation breaks down.  It's purely
luck (and some of the more didactically minded people here would
insist that it's *bad* luck) that your expectation was fulfilled in
this case.

You're making it worse because you store double-precisition floating
point constants in (potentially) higher-precision variables.  You should
be using long-double constants instead:

long double x, y, ymin=0.45L, ystep=0.05L;

y=0.45L+0.05L; x = (y > 0.5L) ? (y - 1.0L) : y;
        y = 0.45L + 0.05L

--

Even if all the snow were burnt, ashes would remain.
--



Sun, 16 Jan 2005 00:52:31 GMT  
 can long double be less precise than double?


AA> long double x,y;
AA>
AA> y=0.45+0.05; x = (y>0.5) ? (y-1) : y;
AA> printf("x=%Lf\n",x);
AA> /* this part gives, as expected, x = 0.5 */
AA>
AA> y=ymin+ystep; x = (y>0.5) ? (y-1) : y;
AA> printf("x=%Lf\n",x);
AA> /* this part gives x = -0.5 !!!! */
AA>
AA> If i change the type from long double to double, i get the expected
AA> result which is 0.5 in both cases.

I'm not sure why you expected 0.5, because 0.45 and 0.05 are not
exactly representable in binary fractions.  There are three
possibilities:

a. 0.45 and 0.05 both round to a binary fraction that's slightly lower
   than the exact value - the sum will be less than 0.5 and you'll get
   your "expected" result.

b. 0.45 and 0.05 round in opposite directions, and sum to exactly 0.5
   - you'll get your "expected" result.

c. 0.45 and 0.05 both round up, summing to something slightly greater
   than 0.5, and you'll be surprised.

Whether each value rounds up or down depends on the value of the first
omitted bit, and therefore on the number of bits of precision.  The
absolute error of each summand will get lower as you reduce the
precision, but the error of the total will sometimes be exactly zero,
and sometimes greater.

This is the reason you shouldn't write code like

  for (i=0.0; i!=1.0; i+=0.1) do_something();

Or is your confusion simply due to the fact that printf doesn't give
an exact result in decimal?  That the value of x in the second case is
slightly higher (less negative) than -0.5, but the difference is way
down in the least significant bit that's not printed?  And that the
first case may or may not be slightly less than 0x5, but you can't
tell from the printout?
--



Sun, 16 Jan 2005 00:52:36 GMT  
 can long double be less precise than double?

Quote:

> Hi, i have a problem with using long double:

> long double x,y,ymin=0.45,ystep=0.05;

> y=0.45+0.05; x = (y>0.5) ? (y-1) : y;
> printf("x=%Lf\n",x);
> /* this part gives, as expected, x = 0.5 */

> y=ymin+ystep; x = (y>0.5) ? (y-1) : y;
> printf("x=%Lf\n",x);
> /* this part gives x = -0.5 !!!! */

> If i change the type from long double to double, i get the expected
> result which is 0.5 in both cases.

There are two issues here:
1. results of rounding inexact representations
2. difference between compile time and run time evaluation.

The exact arithmetic value of 0.45 + 0.05 is 0.5, which causes (y>0.5)
to evaluate false, since y is equal to, not greater than 0.5.  The first
approximation to (y>0.5) is thus false.

Floating point in most computers uses binary notation for the mantissa,
resulting in many numbers not having an exact representation, including
0.45 and 0.05.  They are rounded, in some fashion, to a nearby value
which is representable.  When two floating point numbers are added, the
results are also rounded, in some fashion, to a representable number.
In the first case, the evaluated sum was rounded to a value larger than
0.5, giving you the results you expected.  In the second case, sum was
rounded to a value 0.5 or less, giving you different results.  Both
results should be very very close to each other.  Small rounding errors
are normal for floating point arithmetic.

The reason why the results are different is apparently that the first
expression is evaluated when the program is compiled, since the compiler
knows both operands.  The technique it uses for rounding of the results
differs from the evaluation at run time.  This is normally a quality of
implementation issue, i.e., better implementations should, IMO, give the
same results in both cases, assuming that the rounding mode is not
explicitly changed.

In summary, the results you got are acceptable, as a slight and expected
difference in rounding can make (y>0.5) evaluate as either true or
false.

Thad
--



Sun, 16 Jan 2005 00:52:41 GMT  
 can long double be less precise than double?
No, but it can be less accurate.  Note that 0.45 is not exactly
representable in floating point.

ftp://ftp.quitt.net/Outgoing/goldbergFollowup.pdf

--
#include <standard.disclaimer>
 _
Kevin D Quitt  USA 91351-4454           96.37% of all statistics are made up
Per the FCA, this email address may not be added to any commercial mail list
--



Sun, 16 Jan 2005 23:11:08 GMT  
 can long double be less precise than double?

Quote:
> Hi, i have a problem with using long double:

> long double x,y,ymin=0.45,ystep=0.05;

> y=0.45+0.05; x = (y>0.5) ? (y-1) : y;
> printf("x=%Lf\n",x);
> /* this part gives, as expected, x = 0.5 */

> y=ymin+ystep; x = (y>0.5) ? (y-1) : y;
> printf("x=%Lf\n",x);
> /* this part gives x = -0.5 !!!! */

> If i change the type from long double to double, i get the expected
> result which is 0.5 in both cases.

> i simply do not understand what is going on... don't even know where
> the problem might be.
> (running Linux 2.2.17; processor Pentium III; output of gcc -v  :
>   Reading specs from
> /usr/lib/gcc-lib/i386-slackware-linux/egcs-2.91.66/specs
>   gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
> )

This isn't a problem of different precision.  It's a problem caused by the
fact that *no* floating point representation is precise.   In any
floating point scheme, 0.05 and 0.45 can not be represented exactly.
Try to represent those values in base 2 and you'll find you can't
do it exactly.

Since both values will be stored inexactly, their sum is also likely to be
inexact, i.e. different from 0.5 (although you may get lucky and the
errors cancel out on addition).

You just got lucky when your first example gave what you expected.
With different machines or compilers (associated with different
floating point representations) you could get lucky (or unlucky
depending on how you look at it) with both examples.
--



Sun, 16 Jan 2005 23:11:27 GMT  
 can long double be less precise than double?
Thanks a lot for the responses. i understand it wasn't a very well
thought out question...,
amit
--



Mon, 17 Jan 2005 02:25:19 GMT  
 
 [ 11 post ] 

 Relevant Pages 

1. double(little-endian) --> double(big-endian)

2. epsilon for float, double long double

3. Difference between double and long double?

4. Converting long double to double

5. Internal structure of long double and double

6. diff between double and long double

7. Difference between double & long double

8. Long long and long double

9. result of double*double is no double

10. double precise enough for unsigned short?

11. long long integer and double precision number

12. addition long values to long double value ?

 

 
Powered by phpBB® Forum Software