C/Can this work?
Expert: Mario De Weerd - 10/19/2003
QuestionMy project for my c programming class was to: Write a C program to determine the square root of x using Newton's method. The method is iterative, and during each iteration, a new estimate of the square root of x is calculated based on the previous estimate. The process can be stopped when the difference between the estimate square root and x is less than some tolerance. r is the estimate of the square of x.
The given formula r(new)=r(old)-(r^2(old)-x)/(2*r(old))
Can be terminated when abs(r^2(new)-x)<= tolerance
All input values are read from a file and all output read to a file. Input consist of two double values. The first value will be x, and the second is the termination tolerance. The program must write to the output file( Team Name, course title, and program number all on seperate lines). It must then print what the program does. Program should read all input data from a file named "Program2.dat" Should test for negative values of x, and give a message indicating that the square couldn't be performed.
Here is my program so far:
#include <stdio.h>
#include <math.h>
void main(void){
FILE* inp;
FILE* outp;
double r;
double x;
double a;
inp=fopen("c:Programs.dat","r");
outp=fopen("c:output.out","w");
fprintf(outp,"TeamA\n");
fprintf(outp,"CEE Programming for CEE\n);
fprintf(outp,"Program 2");
fprintf(outp,"This program calculates the square root of a number with Newton's Method");
fscanf(inp,"%3lf",&r);
fscanf(inp,"%3lf",&x);
a= if(x<=0)
fprintf(outp,"Can't calculate negative numbers");
else
while(abs((r^2)-x>=x)
r=(r-((r^2)-x))/(2*r);
fprintf(outp,"The sqaure root is %3lf",a);
fclose(inp);
fclose(outp);
}
Will you please look at this and tell me if this will work correctly, and if not can you tell me how to fix it. I would really appreciate it if you could get it to me before Wednesday. Thank you again.
Stephen Clayton
Cclay64705@aol.com
AnswerHello
I first take your program and add some comments to it.
#include <stdio.h>
#include <math.h>
void main(void){
-> Oh, oh -> you are redefining the main() function. The main function is never a void and should always return an int (the error code). I know that the compiler accepts this, but it is bad programming.
FILE* inp;
FILE* outp;
double r;
double x;
double a;
inp=fopen("c:Programs.dat","r");
outp=fopen("c:output.out","w");
fprintf(outp,"TeamA\n");
fprintf(outp,"CEE Programming for CEE\n);
fprintf(outp,"Program 2");
-> EOL missing.
fprintf(outp,"This program calculates the square root of a number with Newton's Method");
-> EOL missing.
fscanf(inp,"%3lf",&r);
-> This method is not fault-proof against faulty input by the user, but I suppose that it is accepted in the context of the exercise.
fscanf(inp,"%3lf",&x);
a= if(x<=0)
-> On this line you make an assignment to a of the if statement which seems impossible to me. Further, you compare a double to an integer. It is better to write <= 0.0. That will be the same in the end, but it is better programming. It also better to use the curly braces for clarity. I guess that the mistake of "a=" is because you simply wanted to assign the fault tolerance in a and made a typing mistake or so.
fprintf(outp,"Can't calculate negative numbers");
-> Is this really so? The square root of a negative number is an imaginary number. But maybe this is outside the scope of the exercise & you do not know about complex numbers.
else
while(abs((r^2)-x>=x)
-> You forgot to put the parentheses "abs((r^2)-x)>=x". Further it is better to write "abs((r*r)-x)>=x" because a multiplication is more precise and simpler to calculate than the power of a number. Thirdly, depending on wheter abs() is a macro or not, you may need to write fabs(...) where fabs would be the floating point implementation of the abs function (only if abs is not a macro -> probably not the case, but it might be and then you'll need to check if fabs exists. If abs is a function it would be with an integer argument). And finally, you compare the error value to the square value. It should be "abs((r*r)-x)>=a"
r=(r-((r^2)-x))/(2*r);
-> again, write r^2 as r*r.
fprintf(outp,"The sqaure root is %3lf",a);
-> EOL missing, spelling mistake in square and more importantly, "a" is not the result, it is the acceptable error. "r" is the result. Allowing only " digits to express the result is also not a lot, but maybe that is within the scope of the excercise.
fclose(inp);
fclose(outp);
-> and a return (0); [with int main() as indicated above]
}
As a final note. With corrections the above may work in most cases and will probably be acceptable for the exercise. However, in real life this is not sufficient. The value for "a" might be too small for the numbers given and then your program would run forever. You can probably obtain this condition by giving "x" the value of sqrt(MAX_DOUBLE) and "a" a small value (something like 1.0/x).
The solution is to put an upper bound to the number of while loops that you can have. When this upper bound is reached, you'll probably have a good solution with maximum precision. However floating point numbers (even doubles) are limited in what they can represent and therefore, the requested absolute precision can not be obtained.
It would be better to implement a relative precision "abs((r*r)-x)/x >a", where "a" is the relative precision.
Well that is it.