The following code finds the square root of a number, it runs fine unless you compile with MinGW gcc:

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
	double x0,x1,a;
	int i;	
	x1 = 1;
	x0  = 0;
	printf("\nFind square root of: ");
	scanf("%lf",&a);
	for(i = 0; x0 != x1; ++i)
	{
		x0 = x1;
		x1 = .5 * (x1 + a / x1);
//		printf("\nIteration %d - converging to %lf - prev value %lf",i,x1,x0);
		
	}
	
	printf("Finished");
			
	return 0;
}

The problem is if compiled with compilers other than gcc (I have tested it with lcc, visual C++ and borland C++) it reaches "finished" but for gcc it never gets out of the loop. Try to find sqrt of 5, 7 and you will see what I mean. I know about the issues involving comparison of double datatypes, but in this particular case it is guaranteed that x1 will stop changing after certain iterations.

Now for the most interesting part. Uncomment the printf statement within the loop. And you will see everything works fine. I got no clue what's happening inside gcc.

I want to know if anyone's gcc(MinGW) compiler is also behaving the same or not.

Recommended Answers

All 24 Replies

works ok with Dev-C++ (version 4.9.9.2 which uses gcc), just had to add getchar() after the scanf() to flush the '\n' out of the keyboard so that I could see the results before the program terminated.

> I know about the issues involving comparison of double datatypes
"This is a hole, and I know I'm lying at the bottom of it."
What exactly were you expecting to happen?
If you know about the issues, why didn't you code around them and test on each compiler?

> The problem is if compiled with compilers other than gcc (I have tested it with lcc, visual C++ and borland C++
Proving that your code has undefined behaviour.

> but in this particular case it is guaranteed that x1 will stop changing after certain iterations.
Just because the printf outputs "1.234" and "1.234" does not mean the equivalent numeric test for inequality will fail. Printing things to only 6 digits of precision when doubles have 15 digits of precision is going to entail a certain amount of rounding.

> Uncomment the printf statement within the loop. And you will see everything works fine.
Try printing out the value of i at the end of the loop.
Without printf slowing it down, it's probably executing many 1000's more iterations. Which might mean it eventually stumbles upon convergence.

Adding a final "\n" to your printf would be a good idea as well.

Member Avatar for iamthwee
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	float x0,x1,a;

	printf("\nFind square root of: ");
	scanf("%f",&a);
	
	
	float t = 10;
	int i;
	
    for(i = 0; i<100; i++)
	{
        t = t - ((t*t - a)/(2*t));
		
		printf("\nIteration %f ",t);
		
	}
	
	printf("Finished\n");
	getchar();
	getchar();

	//return 0;
}

One more thing, I would use newton's formula for rapid convergence as shown above. It also eliminates the comparison stumbling block.

commented: He did use Newton's formula, don't you know any algebra? +0

"This is a hole, and I know I'm lying at the bottom of it."
What exactly were you expecting to happen?
If you know about the issues, why didn't you code around them and test on each compiler?

There is no hole in my code. I said I am aware of the comparison issue with double/float datatypes. I said so because some of you might jump into the conclusion that checking for inequality between two double datatypes is what's wrong with my code.

Proving that your code has undefined behaviour.

Not necessarily; it could very well be for a bug with the version of gcc I have.

Just because the printf outputs "1.234" and "1.234" does not mean the equivalent numeric test for inequality will fail. Printing things to only 6 digits of precision when doubles have 15 digits of precision is going to entail a certain amount of rounding.

Why did you presume I am relying on the output of printf? Newton raphson method has quadratic convergence which does not require much iteration to get to 15 digits of precision. It is also guranteed that x1 stop changing after certain no of iterations, and when it does that the loop will exit. So I don't see anything wrong with the loop condition.

Try printing out the value of i at the end of the loop.

If I print something within the loop, the program executes just fine. If I don't print anything inside the loop, it seems to go on for ever. THIS weird behaviour is what's bugging me. Do you have the 3.4.2 version of MinGW? Did you try my code with it? If you did, did you see the weird behaviour I mentioned above? That is all I was asking of you.

Adding a final "\n" to your printf would be a good idea as well.

Adding a '\n' to my printf doesn't make the weird behaviour go away, This advice of yours is not only childish but also completely irrelevant to the issue at hand.

works ok with Dev-C++ (version 4.9.9.2 which uses gcc),

The version I am using is 3.4.2 of gcc, I thing DevC++ uses a version greater than 3.4.2. I checked sourcedforge for the latest 'current' version, but it was still 3.4.2. Only the 'candidate' has a newer version.

I still can't explain the way my program is behaving. Why printing inside the loop makes the program work and not printing inside the loop takes it into an infinite loop(when compiled using MinGW gcc version 3.4.2).

>>The version I am using is 3.4.2 of gcc

Then upgrade to the newest version. Why use a buggy compiler (as if VC++ 6.0 is bug-free!:mrgreen: )

> I said so because some of you might jump into the conclusion that checking for
> inequality between two double datatypes is what's wrong with my code.
http://docs.sun.com/source/806-3568/ncg_goldberg.html
http://c-faq.com/fp/fpequal.html
Just because you believe that it "isn't a problem for me" doesn't mean that it isn't a problem. The fact that it works for you sometimes, with some compilers doesn't mean that there isn't a problem.

> it could very well be for a bug with the version of gcc I have.
Statements like this require huge amounts of proof - you don't have that.
Did you disassemble all the generated code to find out what the compiler really did?
Besides, if you did, you should have visited
http://www.mingw.org/bugs.shtml

Not to mention

$ gcc -W -Wall -ansi -pedantic -O2 foo.c
foo.c: In function ‘main’:
foo.c:16: warning: ISO C90 does not support the ‘%lf’ printf format
foo.c:16: warning: ISO C90 does not support the ‘%lf’ printf format

Read
http://www.mingw.org/mingwfaq.shtml
"MinGW uses the Microsoft runtime libraries, distributed with the Windows operating system"
It does not use the standard GNU LibC implementation, but inherits all the bugs and features of the host libraries.
Maybe by feeding printf() bogus format sequences it's corrupting the stack and the rest of your local variables into the bargain.
Do you still see a problem when you use correct printf format controls?

> Do you have the 3.4.2 version of MinGW? Did you try my code with it? If you did, did you see the weird behaviour I mentioned above?
No, No and No.
Generally speaking, I try and sort out the obvious deficiencies (such as undefined or suspicious behavior) before actually bothering to try and run code myself.


> Adding a '\n' to my printf doesn't make the weird behaviour go away, This advice of
> yours is not only childish but also completely irrelevant to the issue at hand.
Here's chapter and verse from the C89 standard.

4.9.2 Streams

Input and output, whether to or from physical devices such as terminals and tape drives, or whether to or from files supported on structured storage devices, are mapped into logical data streams, whose properties are more uniform than their various inputs and outputs. Two forms of mapping are supported, for text streams and for binary streams .99

A text stream is an ordered sequence of characters composed into lines , each line consisting of zero or more characters plus a terminating new-line character. Whether the last line requires a terminating new-line character is implementation-defined. Characters may have to be added, altered, or deleted on input and output to conform to differing conventions for representing text in the host environment. Thus, there need not be a one-to-one correspondence between the characters in a stream and those in the external representation. Data read in from a text stream will necessarily compare equal to the data that were earlier written out to that stream only if: the data consist only of printable characters and the control characters horizontal tab and new-line; no new-line character is immediately preceded by space characters; and the last character is a new-line character. Whether space characters that are written out immediately before a new-line character appear when read in is implementation-defined.

Again, all this "works for me with the foo and bar compilers" doesn't make your code bug free, or free from different implementation specific behaviours.
And how would you know whether it was an issue or not, since you have yet to figure out the answer to the question?

http://docs.sun.com/source/806-3568/ncg_goldberg.html
http://c-faq.com/fp/fpequal.html
Just because you believe that it "isn't a problem for me" doesn't mean that it isn't a problem. The fact that it works for you sometimes, with some compilers doesn't mean that there isn't a problem.

I read the first article back in my "Computer organisation and design" class regarding how to represent real numbers inside computers. And I have already told you I am completely aware that the following code is wrong:

double x;
for(x = 0; x != 9.9; x += .1)
      //do something

However the following block from my code is perfectly alright:

for(i = 0; x0 != x1; ++i)
{ 
     x0 = x1;
     x1 = .5 * (x1 + a / x1);
     //printf("\nIteration %d - converging to %lf - prev value %lf",i,x1,x0);


}

if you can't see the difference, that's very unfortunate.

Statements like this require huge amounts of proof - you don't have that.
Did you disassemble all the generated code to find out what the compiler really did?

LOL, when did statements like "this could very well be a bug with gcc" requires "huge amount of proof". In fact, I posted my code here just TO VERIFY if it was indeed a bug with the version of gcc I have or not. I wanted to see if anyone else gets the same output as I am getting.

As for the format specifier %lf for printf() i don't think it's an issue with MinGW gcc which has implemented a great deal of C99 standard. ABOVE ALL the code works fine when I uncomment the printf() statement not the other way.

No, No and No.

And that's why I am prolly wasting my time here.

Instead of putting up a whole bunch of "this might be the problem"s you could have been more specific. That might have been more useful.

As for printing a final '\n' - that's more of an issue with input streams. Printing a newline to the console is the least of the worries here.

LOL, when did statements like "this could very well be a bug with gcc" requires "huge amount of proof".

For quite a long time, actually.
http://www.catb.org/~esr/faqs/smart-questions.html#id264997

As for the format specifier %lf for printf() i don't think it's an issue with MinGW gcc

The general rule of thumb is this: once you do undefined behavior, the rest of the program is undefined.

For quite a long time, actually.
http://www.catb.org/~esr/faqs/smart-....html#id264997

I never claimed to have found a bug in gcc. I merely suggested that it could be a possibility. If you look at my first post I was here to clarify if it was due to a bug with the gcc or due to something wrong with my code.

The general rule of thumb is this: once you do undefined behavior, the rest of the program is undefined.

So using %lf with printf is undefined behaviour? That is certainly news to me. If that's true there are three possible actions that should be taken:

1. The ones who specified this to be an undefind behaviour in the C standard should be shot dead for creating this confusion in the first place. If %lu is okay why should %lf be not. It sounds so natural.

2. The authors who wrote books on C and said %lf is a valid printf format specifier should be shot dead for misleading/misinforming us.

3. Dave Sinkula, Narue, Ancient Dragon, Rashakifol and everyone else possesing a much better knowledge on C should be shot dead since they did not point this one out to me before;I believe I have used %lf with printf many a times before in this forum.

With all that said my gcc still acts weird even if I use %f instead of %lf with printf (specially when the printf statement was inside a comment after all ). But I guess you can't see it for yourself. So I will take the pain of video recording my desktop activity and posting it here. I am currently posting from elsewhere. I will do so as soon as I get home. I must see it to its end.

>I merely suggested that it could be a possibility.
It's never a possibility until you've exhausted all other options.

>So using %lf with printf is undefined behaviour?
In C89 it's undefined. In C99 the length modifier is quietly ignored because the committee realized this confusion was a very real problem.

>If %lu is okay why should %lf be not.
Because l is meant for integers, not floating-point.

>It sounds so natural.
Just because you see symmetry doesn't mean there is symmetry. What does %lf mean? Double? No, that's what %f means because varargs arguments use pre-C89 promotion rules. Long double? No, that's what %Lf is for. Why a capital L for long double? Because the committee realized that some moron would use %lf thinking it meant double, pass a double, and cause undefined behavior when printf treated it as a long double.

>The authors who wrote books on C and said %lf is a valid printf format specifier should be shot dead
Yes, but not for misleading you. They should be shot dead for trying to teach a language that they still haven't learned properly.

>Dave Sinkula, Narue, Ancient Dragon, Rashakifol and everyone else
>possesing a much better knowledge on C should be shot dead since they
>did not point this one out to me before
It's not our job to delint your programs. If it bothers you so much that we don't take the time to point out every little problem then go shell out $500 for PCLint and do it yourself.

>I believe I have used %lf with printf many a times before in this forum.
This is a problem that can easily be missed unless you're looking for it. Despite your obvious expectations, we're not capable of finding every little bug at a glance. I spend a lot of time looking closely at my code, referring to the standard, and using powerful tools like lint to catch as many problems as I can. I don't usually expend the same amount of effort on every piece of code posted to these forums by other people.

> With all that said my gcc still acts weird even if I use %f instead of %lf with printf
I use MinGW's 3.4.2 version of gcc, and I can't reproduce your problem. My educated guess would be that you really are hitting a floating-point rounding issue and it has nothing to do with gcc. What OS and processor do you use? Also, can you post a dozen or so iterations of the execution with the printf uncommented?

Just for you, I downloaded and installed Mingw.

Guess what - nothing unusual happening here either, despite your broken code.

Anyway, I've cleaned it up a bit (stop it looping forever for example) and shown an example session - I suggest you do the same for a problem case as Narue suggests.

#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);			
	return 0;
}


$ gcc -v
Reading specs from c:/mingw/bin/../lib/gcc/mingw32/3.4.2/specs
Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable-languages=c,c++,f77,ada,objc,java --disable-win32-registry --disable-shared --enable-sjlj-exceptions --enable-libgcj --disable-java-awt --without-x --enable-java-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-hash-synchronization --enable-libstdcxx-debug
Thread model: win32
gcc version 3.4.2 (mingw-special)
$ gcc -W -Wall -ansi -pedantic -O2 -DINCLUDE_PRINTF prog.c
$ ./a.exe 
Find square root of: 5.7
Iteration 0 - converging to 3.350000 - prev value 1.000000
Iteration 1 - converging to 2.525746 - prev value 3.350000
Iteration 2 - converging to 2.391253 - prev value 2.525746
Iteration 3 - converging to 2.387470 - prev value 2.391253
Iteration 4 - converging to 2.387467 - prev value 2.387470
Iteration 5 - converging to 2.387467 - prev value 2.387467
Iteration 6 - converging to 2.387467 - prev value 2.387467
Finished in 7 iterations

My next guess is you have some crusty old pentium with an uncorrected FDIV bug. Other than that, I can't reproduce the problem so unless you post more details, there's not a lot else to do.

Thanks everyone for being so patient with me, especially Salem who actually downloaded MinGW gcc. I really appreciate that!

Here's the screen capture of what I am getting. First I compile the program with the printf statement commented. In this case the loop never ends. I had to Ctrl + C to kill it.

In the next case I uncomment the printf statement and the program works as expected.

The issue is only with MinGW gcc version 3.4.2. I have tested the code with lcc-win32, visual C++ 6.0 and Borland C++ 5.5.

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
	double x0, x1, a;
	int i;	
	x1 = 1;
	x0 = 0;	
	printf("\nFind square root of: ");
	scanf("%lf",&a);
			
	for(i = 0; x0 != x1; ++i)
	{
		x0 =  x1;
		x1 = 0.5 * (x1 + a / x1);
		printf("\nIteration %i: x1 = %.15f x0 = %.15f", i, x0, x1);
	}
	
	printf("\nAnswer: %.15f\n",x1);
	return 0;
}

Unzip and open the gcc.html file with your browser. You will see it yourselves.

Just because you see symmetry doesn't mean there is symmetry. What does %lf mean? Double? No, that's what %f means because varargs arguments use pre-C89 promotion rules. Long double? No, that's what %Lf is for. Why a capital L for long double? Because the committee realized that some moron would use %lf thinking it meant double, pass a double, and cause undefined behavior when printf treated it as a long double.

%lf is valid for scanf(), so it is natural for anyone to think it is also valid for printf(). Things like this is easy to miss unless someone explicitly mentions it.

Now I want to know how much does this C and C++ standard costs? Or can you direct me to a modern book on C(not C++), cos I am thinking of getting a book that really teaches these subtle points. K&R, I guess, has become quite outdated.

>%lf is valid for scanf()
Yes, because scanf expects a pointer, and pointers must be appropriately typed. printf doesn't require a pointer, and default promotions apply.

>Things like this is easy to miss unless someone explicitly mentions it.
I agree, but C is a subtle language. Why do you think it takes so many years to become proficient with it?

>Now I want to know how much does this C and C++ standard costs?
$18 for the PDF version at www.ansi.org, or about $60 for the Wiley hardcopy, or about $200 for the official ANSI hardcopy.

>Or can you direct me to a modern book on C
A good reference that makes few mistakes is C: A Reference Manual (5th Edition) by Harbison and Steele. It's a nice alternative to the standard if you can't take hundreds of pages of legalese. But there are a few minor points (that should only come up in a debate of pedantry) where C: A Reference Manual is not entirely accurate.

>K&R, I guess, has become quite outdated.
Not really. K&R is still my most referenced book on C. I'm on my 3rd copy because the other two fell apart from overuse, and the binding is excellent.

>You will see it yourselves.
My guess remains the same. First fix your floating-point comparison so that it uses a fudge factor. If the problem remains, post the code you used. Since we can't reproduce your problem, the only way we can help is to offer suggestions and make sure that your code is 100% correct for troubleshooting.

First fix your floating-point comparison so that it uses a fudge factor.

First you explain to me how come uncommenting a printf() statement makes the loop end. This simply doesn't make any sense.

Within a few iterations the new value of x1 differs so small from the prev value of x1 that it is well beyond the precision of 15 decimal places. x1 is then unchanged. So a match between x0 and x1 should be true(since I do a x0 = x1). The loop should exit. It works with all the compilers. Even you people could not reproduce the problem.

Not really. K&R is still my most referenced book on C

Oh yeah it is. K&R IS outdated. K&R was written around C89 standard. It doesn't teach you the features available in C99 . You can still use it as a reference because most of the compilers still haven't implemented all of C99. So that you can tell people,"Hey not all compilers have implemented C99 fully, so don't use this or that; your code has undefined behaviour according to C89, your code is broken according to C89 etc. etc." In my view that book is outdated.

>First you explain to me how come uncommenting a printf() statement makes the loop end.
No, fix your damn code first. Then we'll talk about weird things happening. If you want help, stop being a prick about the help you're getting. If you want to be a smartass, we'll be happy to offer you a cold shoulder.

>You can still use it as a reference because most of the compilers still haven't implemented all of C99.
When you're intimately familiar with both C89 and C99, then you're welcome to debate the validity of K&R's content. Until then, take my word for it.

>In my view that book is outdated.
In my view you lack the foundation to make that judgement.

No, fix your damn code first.

If you run the loop for say 50 times that's enough most of the time to get the desired result. So instead of using x1 != x0, I would use the following code

for(i = 0; i < 50; ++i)
   x = .5 * (x + a / x);

But the number of iteration that is required depends very much on the value of a, for some it would require 5 iterations and for some it would take 19. So why should I run the code 50 times for each value of a. That's not very elegant IMHO.

The second method that came into my mind was to use fabs(a - x1 * x1) > 0.00000000000001 to make the loop continue until it reaches 15 decimal precision. Then again for the most of the values of a it goes into a infinite loop. I guess that's quite expected and I should use something like this: fabs(fabs(a - x1 * x1) - 0.00000000000001) )> (FUDGE_FACTOR) . I am just not quite sure what to use for the fudge factor so that I do get the precision upto 15 decimal places.
Originally I was solving the follwing problem
x_0 = 1, x_{i + 1} = \frac{1}{2}(x_i + \frac{a}{x_i})

x_i \rightarrow \sqrt{a} as i \rightarrow \infty

I thought x0 != x1 would be the best way to simulate i \rightarrow \infty.

Can't you find a better way of conveying your results other than some bloated shockwave flash file, which by the way I've no intention of running while I'm at work.

Does the enhanced exit condition in my example code loop forever on your machine as well?

Does the enhanced exit condition in my example code loop forever on your machine as well?

This is what happens when I use your code. The effect is same as mine. This time it's in GIF format. Hope that's okay with you.

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

#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

$ 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.

`-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.

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

$ 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

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.

commented: That was really helpfull - Asif_NSU +3

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?

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.)

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.

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

> 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.

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.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.