| | |
what's with gcc?
Please support our C++ advertiser: Intel Parallel Studio Home
![]() |
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
Here are my results - the last two are the more interesting ones
Now, the real explanation becomes more apparent when you read the manual page for that flag.
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
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.
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)
#include<stdio.h> #include<stdlib.h> int main(void) { double x0,x1,a; int i; x1 = 1; x0 = 0; 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 } printf("Finished in %d iterations\n",i); printf("Results: %.15f, %.15f\n",x0,x1); { union { double a; unsigned long b[2]; } v; v.a = x0; printf( "X0 in binary = %lu %lu\n", v.b[0], v.b[1] ); v.a = x1; printf( "X1 in binary = %lu %lu\n", v.b[0], v.b[1] ); } return 0; }
Here are my results - the last two are the more interesting ones
C++ Syntax (Toggle Plain Text)
$ gcc -W -Wall -ansi -pedantic -O2 -DINCLUDE_PRINTF foo.c $ ./a.exe 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 Finished in 7 iterations Results: 2.236067977499790, 2.236067977499790 X0 in binary = 2610427048 1073865591 X1 in binary = 2610427048 1073865591 $ gcc -W -Wall -ansi -pedantic -O2 foo.c $ ./a.exe Find square root of: 5 Finished in 100 iterations Results: 2.236067977499790, 2.236067977499790 X0 in binary = 2610427048 1073865591 X1 in binary = 2610427048 1073865591 $ gcc -W -Wall -ansi -pedantic -O2 -ffloat-store foo.c $ ./a.exe Find square root of: 5 Finished in 7 iterations Results: 2.236067977499790, 2.236067977499790 X0 in binary = 2610427048 1073865591 X1 in binary = 2610427048 1073865591 $
Now, the real explanation becomes more apparent when you read the manual page for that flag.
C++ Syntax (Toggle Plain Text)
`-ffloat-store' Do not store floating point variables in registers, and inhibit other options that might change whether a floating point value is taken from a register or memory. This option prevents undesirable excess precision on machines such as the 68000 where the floating registers (of the 68881) keep more precision than a `double' is supposed to have. Similarly for the x86 architecture. For most programs, the excess precision does only good, but a few programs rely on the precise definition of IEEE floating point. Use `-ffloat-store' for such programs, after modifying them to store all pertinent intermediate computations into variables.
Now, if you combine all this with
C++ Syntax (Toggle Plain Text)
$ gcc -W -Wall -ansi -pedantic -O2 -ffloat-store -Wfloat-equal foo.c foo.c: In function `main': foo.c:14: warning: comparing floating point with == or != is unsafe
> That's not very elegant IMHO.
Robust use of floating point is no easy ride.
•
•
•
•
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.
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? "He who mixes with people and endures the harm they do is better than he who does not mix and endures." (Tirmidhi)
•
•
•
•
Originally Posted by Asif_NSU
There has to be a better way.
#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;
}•
•
•
•
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
"One of the methods used by statists to destroy capitalism consists in establishing controls that tie a given industry hand and foot, making it unable to solve its problems, then declaring that freedom has failed and stronger controls are necessary." --Ayn Rand
> 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.
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.
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.
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.
"He who mixes with people and endures the harm they do is better than he who does not mix and endures." (Tirmidhi)
![]() |
Similar Threads
- win32 gcc cross compiling for linux target (C)
- Problem with basic templates on GCC (C++)
- from gcc to VC++.Net (C++)
- error when compiling murphy's law with gcc (C)
- installing vmware tools on mandrake 10 (*nix Software)
Other Threads in the C++ Forum
- Previous Thread: finding max value of 10 integers
- Next Thread: New to C++
Views: 5457 | Replies: 24
| Thread Tools | Search this Thread |
Tag cloud for C++
6 api application array arrays based beginner binary c++ c/c++ calculator char char* class classes code coding compile compiler console conversion convert count data database delete developer display dll dynamiccharacterarray email encryption error file format forms fstream function functions game generator givemetehcodez graph iamthwee ifstream image input int java lib list loop looping loops map math matrix memory multiple newbie news number numbertoword output pointer problem program programming project python random read recursion recursive reference return rpg search simple sort sorting spoonfeeding string strings struct template templates text tree url variable vector video visual visualstudio win32 windows winsock wordfrequency wxwidgets






