943,916 Members | Top Members by Rank

Ad:
  • C++ Discussion Thread
  • Unsolved
  • Views: 7589
  • C++ RSS
You are currently viewing page 3 of this multi-page discussion thread; Jump to the first page
May 16th, 2006
1

Re: what's with gcc?

I don't know why you edited the file when the #ifdef was there just to make it so you didn't need to edit it :shrug:

Anyway, I'm now seeing the same problem on cygwin as well - which I suppose is progress in itself.

Here's my modified code - it's the same with a bit of extra debug on the end
C++ Syntax (Toggle Plain Text)
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3.  
  4. int main(void)
  5. {
  6. double x0,x1,a;
  7. int i;
  8.  
  9. x1 = 1;
  10. x0 = 0;
  11. printf("Find square root of: ");
  12. fflush(stdout);
  13. scanf("%lf",&a);
  14. for(i = 0; i < 100 && x0 != x1; ++i)
  15. {
  16. x0 = x1;
  17. x1 = .5 * (x1 + a / x1);
  18. #ifdef INCLUDE_PRINTF
  19. printf("Iteration %d - converging to %f - prev value %f\n",i,x1,x0);
  20. #endif
  21. }
  22.  
  23. printf("Finished in %d iterations\n",i);
  24. printf("Results: %.15f, %.15f\n",x0,x1);
  25. {
  26. union { double a; unsigned long b[2]; } v;
  27. v.a = x0;
  28. printf( "X0 in binary = %lu %lu\n", v.b[0], v.b[1] );
  29. v.a = x1;
  30. printf( "X1 in binary = %lu %lu\n", v.b[0], v.b[1] );
  31. }
  32. return 0;
  33. }

Here are my results - the last two are the more interesting ones
C++ Syntax (Toggle Plain Text)
  1. $ gcc -W -Wall -ansi -pedantic -O2 -DINCLUDE_PRINTF foo.c
  2. $ ./a.exe
  3. Find square root of: 5
  4. Iteration 0 - converging to 3.000000 - prev value 1.000000
  5. Iteration 1 - converging to 2.333333 - prev value 3.000000
  6. Iteration 2 - converging to 2.238095 - prev value 2.333333
  7. Iteration 3 - converging to 2.236069 - prev value 2.238095
  8. Iteration 4 - converging to 2.236068 - prev value 2.236069
  9. Iteration 5 - converging to 2.236068 - prev value 2.236068
  10. Iteration 6 - converging to 2.236068 - prev value 2.236068
  11. Finished in 7 iterations
  12. Results: 2.236067977499790, 2.236067977499790
  13. X0 in binary = 2610427048 1073865591
  14. X1 in binary = 2610427048 1073865591
  15.  
  16. $ gcc -W -Wall -ansi -pedantic -O2 foo.c
  17. $ ./a.exe
  18. Find square root of: 5
  19. Finished in 100 iterations
  20. Results: 2.236067977499790, 2.236067977499790
  21. X0 in binary = 2610427048 1073865591
  22. X1 in binary = 2610427048 1073865591
  23.  
  24. $ gcc -W -Wall -ansi -pedantic -O2 -ffloat-store foo.c
  25. $ ./a.exe
  26. Find square root of: 5
  27. Finished in 7 iterations
  28. Results: 2.236067977499790, 2.236067977499790
  29. X0 in binary = 2610427048 1073865591
  30. X1 in binary = 2610427048 1073865591
  31. $

Now, the real explanation becomes more apparent when you read the manual page for that flag.
C++ Syntax (Toggle Plain Text)
  1. `-ffloat-store'
  2. Do not store floating point variables in registers, and inhibit
  3. other options that might change whether a floating point value is
  4. taken from a register or memory.
  5.  
  6. This option prevents undesirable excess precision on machines such
  7. as the 68000 where the floating registers (of the 68881) keep more
  8. precision than a `double' is supposed to have. Similarly for the
  9. x86 architecture. For most programs, the excess precision does
  10. only good, but a few programs rely on the precise definition of
  11. IEEE floating point. Use `-ffloat-store' for such programs, after
  12. modifying them to store all pertinent intermediate computations
  13. into variables.
  14.  
With less code there (without the printf), the compiler can optimise out some implied floating point store and load instructions, which wash away the last few bits of precision which are present in the FPU registers, but not present in a double. By losing this extra precision, your loop takes a different number of iterations to complete.

Now, if you combine all this with
C++ Syntax (Toggle Plain Text)
  1. $ gcc -W -Wall -ansi -pedantic -O2 -ffloat-store -Wfloat-equal foo.c
  2. foo.c: In function `main':
  3. foo.c:14: warning: comparing floating point with == or != is unsafe
  4.  
Which brings us nicely back to the start of the argument which I said that you can't compare floating point numbers, but which you keep insisting is OK and keep ignoring what people with vastly more experience than you keep telling you.

> That's not very elegant IMHO.
Robust use of floating point is no easy ride.
Team Colleague
Reputation Points: 5862
Solved Threads: 950
Posting Sage
Salem is offline Offline
7,164 posts
since Dec 2005
May 16th, 2006
1

Re: what's with gcc?

Quote ...
Which brings us nicely back to the start of the argument which I said that you can't compare floating point numbers, but which you keep insisting is OK and keep ignoring what people with vastly more experience than you keep telling you.
Yeah! But you did not give any explanation that time and it worked well on all the other compilers. All my common sense told me it's something to do with gcc - the compiler itself. Besides the warning for floating point equality is there because you made the compiler to throw that warning by -Wfloat-equal. Even now I feel -ffloat-store should have been activated by default.

And should not be these details like how it's stored in the FPU be well hidden from the programmers point of view? We are only supposed to think in terms of the datatype present in the C programming language. It looks like I have to understand all the nitty gritty internal details of the compiler before actually compiling a very simple program with it.

So is there no way other than for(i = 0; i < 50; ++i)? Come on man! There has to be a better way. What am I gonna do if I am asked why I run the loop for 50 times even for numbers that require only 6 or 7 iterations? Tell them to visit this link?
Reputation Points: 113
Solved Threads: 3
Posting Whiz
Asif_NSU is offline Offline
353 posts
since Apr 2004
May 16th, 2006
0

Re: what's with gcc?

Quote originally posted by Asif_NSU ...
There has to be a better way.
How about the way that was mentioned via the link in post #7? (Which was not to compare floating point values for equality -- a recurring theme in this thread, by the way.)
Quote originally posted by Salem ...
http://c-faq.com/fp/fpequal.html
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>

int main(void)
{
   double x0 = 0, x1 = 1, a;
   int i;
   printf("Find square root of: ");
   fflush(stdout);
   scanf("%lf",&a);
   for ( i = 0; i < 100 && x0 != x1; ++i )
   {
      x0 = x1;
      x1 = .5 * (x1 + a / x1);
#ifdef INCLUDE_PRINTF
      printf("Iteration %d - converging to %f - prev value %f\n",i,x1,x0);
#endif
      {
         double epsilon = DBL_EPSILON * fabs(x1);
         if ( fabs(x1 - x0) <= epsilon )
         {
            printf("reached epsilon of %g\n", epsilon);
            break;
         }
      }
   }
   printf("Finished in %d iterations\n",i);
   printf("Results: %.15f, %.15f\n",x0,x1);
   return 0;
}
My outputs are as follows.
Quote ...
H:\Forum\C>C:/Dev-Cpp/bin/gcc.exe -W -Wall -ansi -pedantic -O2 ../main.c

H:\Forum\C>a
Find square root of: 5
reached epsilon of 4.96507e-016
Finished in 6 iterations
Results: 2.236067977499790, 2.236067977499790

H:\Forum\C>a
Find square root of: 7
reached epsilon of 5.87475e-016
Finished in 6 iterations
Results: 2.645751311064591, 2.645751311064591

H:\Forum\C>C:/Dev-Cpp/bin/gcc.exe -W -Wall -ansi -pedantic -O2 -DINCLUDE_PRINTF ../main.c

H:\Forum\C>a
Find square root of: 5
Iteration 0 - converging to 3.000000 - prev value 1.000000
Iteration 1 - converging to 2.333333 - prev value 3.000000
Iteration 2 - converging to 2.238095 - prev value 2.333333
Iteration 3 - converging to 2.236069 - prev value 2.238095
Iteration 4 - converging to 2.236068 - prev value 2.236069
Iteration 5 - converging to 2.236068 - prev value 2.236068
Iteration 6 - converging to 2.236068 - prev value 2.236068
reached epsilon of 4.96507e-016
Finished in 6 iterations
Results: 2.236067977499790, 2.236067977499790

H:\Forum\C>a
Find square root of: 7
Iteration 0 - converging to 4.000000 - prev value 1.000000
Iteration 1 - converging to 2.875000 - prev value 4.000000
Iteration 2 - converging to 2.654891 - prev value 2.875000
Iteration 3 - converging to 2.645767 - prev value 2.654891
Iteration 4 - converging to 2.645751 - prev value 2.645767
Iteration 5 - converging to 2.645751 - prev value 2.645751
Iteration 6 - converging to 2.645751 - prev value 2.645751
reached epsilon of 5.87475e-016
Finished in 6 iterations
Results: 2.645751311064591, 2.645751311064591
Team Colleague
Reputation Points: 2780
Solved Threads: 312
long time no c
Dave Sinkula is offline Offline
4,790 posts
since Apr 2004
May 16th, 2006
0

Re: what's with gcc?

> So is there no way other than for(i = 0; i < 50; ++i)? Come on man! There has to be a better way
yes, you code something which works on either absolute or relative errors, which we're now getting pretty fed up of telling you about.

> Besides the warning for floating point equality is there because you made the compiler to throw that warning
Do you imagine that compiler writers just throw these things in for fun, or because there is a real problem which needs to be addressed?

The lack of a warning from the compiler does not constitute a proof of correctness on your part.

> Even now I feel -ffloat-store should have been activated by default.
Erm, read the help for that flag - it serves no purpose unless you specifically rely on a particular FP behaviour (like you do).
Better written code wouldn't give a toss about the extra precision, and would get a performance benefit by not being always forced into load-store operations just for your benefit.

> have to understand all the nitty gritty internal details of the compiler
WRONG!!!!!
You need a better understanding of the language, not the implementation.

Knowing how the foo compiler implements it will not help you at all with understanding the bar compiler.

Knowing the standard inside out is what allows you to write portable code, not the grubby details of a specific implementation.

> Yeah! But you did not give any explanation that time and it worked well on all the other compilers
Are you paying for a 24hr service?
Since you insist on writing code with undefined behaviour, there are many many possible ways in which it could be going wrong.

I mean, you never posted your command line options until today.

So until someone else (me) managed to guess which options you were using, or at least some options which showed up the same problem, it was all finger in the air stuff.
Team Colleague
Reputation Points: 5862
Solved Threads: 950
Posting Sage
Salem is offline Offline
7,164 posts
since Dec 2005
May 16th, 2006
0

Re: what's with gcc?

Well, atleast I think I have learned some very good lessons from this thread.

Next time I post at daniweb C and C++ forum I promise I will be at a different level than I am currently now - which despite my efforts has remained to be "a-bit-better-than-beginner", although it has already been 2 years since I was introuduced to C. Looks like I need to take some hiatus from my usual university work if I want to gain any workable skill in C.

Take care...until we meet again.
Reputation Points: 113
Solved Threads: 3
Posting Whiz
Asif_NSU is offline Offline
353 posts
since Apr 2004

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C++ Forum Timeline: finding max value of 10 integers
Next Thread in C++ Forum Timeline: New to C++





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC