LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-18-2013, 04:15 PM   #1
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora/Pop!_OS
Posts: 2,983

Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
messed up my loop with pointers. help please.


we are trying to create a script that solves for square root. i have a working function provided by the prof. i think my error is in my while loop, but im not 100%.

Code:
int main(void)
{
	double N, NG, LG, *PLG, epsilon, root;	// setting all variables to type double

	epsilon = 0.005;			// setting error tolerance to 0.005
	LG = 1.0;				// setting initial guess value

	printf("\nPlease enter the number you wish to find the square root: ");
	scanf("%lf",&N);	// getting input from user

	NG = 0.5 * (LG + (N / LG));

	while ( NG - LG <= epsilon )
	{
		*PLG=NG;
		NG = 0.5 * (*PLG + (N / *PLG));
	}

	printf("The square root of %.2lf is %.3lf\n", N, NG);
}
This runs the first time, but then stops. it never goes back in when the error is outside of my epsilon value.

Code:
ssma-imac:ENG-3211 ssma$ gcc -o hw_4_1 hw_4_1.c
ssma-imac:ENG-3211 ssma$ ./hw_4_1

Please enter the number you wish to find the square root: 4
The square root of 4.00 is 2.500
when i run this by hand it should take 3 attempts and come up with an answer of 2.0006 that should be reported as 2.000.

im guessing that by setting NG = 0.5 * ( LG + (N / LG)); before the while loop that is causing the issue.

I just dont know how to get the NG inside of the while loop for the test conditions for my error checking.

pointing me in the right direction would be great. please no exact code changes or providing of exact code, examples are great. this is homework.

side not question. in class the prof. indicated that as long as you have a variable declared you dont need to also declare the pointer value if they are the same. ex:

doubt LG;

*LG = NG

That is what one of his examples had and I asked about it in class. He indicated that this is fine because *LG will point to the memory location of LG, but when i *LG = NG it will change the value stored at NG to the value pointed to by LG. I think i said that semi clear.

I was receiving unary * errors when compiling with the above example. I had to put *PLG at the top of my script to get the unary error to go away...

whats going on there?

Last edited by lleb; 07-18-2013 at 04:19 PM.
 
Old 07-18-2013, 04:53 PM   #2
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora/Pop!_OS
Posts: 2,983

Original Poster
Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
well i have made some progress, but now my test condition is never coming true:

Code:
int main(void)
{
	double N, NG, LG, *PLG, epsilon, root;	// setting all variables to type double

	epsilon = 0.005;			// setting error tolerance to 0.005
	LG = 1.0;				// setting initial guess value

	printf("\nPlease enter the number you wish to find the square root: ");
	scanf("%lf",&N);	// getting input from user

	//NG = 0.5 * (LG + (N / LG));

//	while ( NG - LG <= epsilon )
//	{
		//*PLG=NG;
//		NG = 0.5 * (LG + (N / LG));
//	}

//	printf("The square root of %.2lf is %.3lf\n", N, NG);
//}	


for (LG = 1; NG - LG <= epsilon; LG = NG)
	{
		NG = 0.5 * (LG + (N / LG));
		printf("%.2lf      %.3lf\n", N, NG);
	}

	printf("\nThe square root of %.2lf is %.3lf\n", N, NG);
}
should not the NG - LG <= epsilon become true after the difference is less then 0.005?

Code:
ssma-imac:ENG-3211 ssma$ ./hw_4_1

Please enter the number you wish to find the square root: 4
4.00      2.500
4.00      2.050
4.00      2.001
4.00      2.000
4.00      2.000
4.00      2.000
4.00      2.000
4.00      2.000
...
it will run until i manually break the program. never getting out of the for loop. also what would be a better way of setting LG = NG like i have in my update section for my for?
 
Old 07-18-2013, 08:43 PM   #3
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
now my test condition is never coming true:
...
should not the NG - LG <= epsilon become true after the difference is less then 0.005?
Actually your test condition is never becoming false. When the loop is entered the first time NG hasn't been set so its value is arbitrary (gcc ought to warn about this, but it doesn't). On subsequent iterations, because you set LG = NG in the update statement NG - LG = 0 which is always less than epsilon.
  • Don't evaluate unset variables:
    either NG should have a value before entering the loop, or use a do while loop instead
  • setting LG = NG just before the test makes the test useless, you should put that assignment elsewhere
  • your test is backwards
  • you should have a fabs() call in your test

Quote:
side not question. in class the prof. indicated that as long as you have a variable declared you dont need to also declare the pointer value if they are the same. ex:

doubt LG;

*LG = NG

That is what one of his examples had and I asked about it in class. He indicated that this is fine because *LG will point to the memory location of LG, but when i *LG = NG it will change the value stored at NG to the value pointed to by LG. I think i said that semi clear.
That is quite wrong, either your professor doesn't know how to program in C, or you completely misunderstood what he was saying. You must always declare variables before using them, no exceptions. In the example code there, unless there are some other statements assigning to LG the effect of it will to write the value of NG to some random location causing memory corruption and/or crash, except that LG is not being declared as a pointer so it won't even compile...
 
1 members found this post helpful.
Old 07-18-2013, 09:00 PM   #4
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora/Pop!_OS
Posts: 2,983

Original Poster
Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
ntubski, thank you for the reply. I have made some adjustments and I did try a do while loop, but i must of made the similar mistake by setting LG = NG before running the test. In fact i did find the fabs() for my epsilon before you posted. so at least im on the right track with that.

here is what i have that is working, but never leaving the loop:

Code:
do	{
	NG = 0.5 * (LG + (N / LG));
	printf("%.2lf      %.3lf\n", N, NG);
	LG = NG;
	}	while (fabs(NG - LG) < epsilon);

	printf("\nThe square root of %.2lf is %.3lf\n", N, NG);
}
now if i follow what you said even though NG is now assigned a value, because i am setting the new value of NG before i run my test it will always fail, or never become false. if i leave out the LG = NG in the above do while loop it fails to get past the first loop and prints out the wrong value.

That is where im stuck. do i need additional variables? i am just not seeing how i can update the value of LG with the results of NG if the condition is not met without putting it in the do section of the loop.

Quote:
That is quite wrong, either your professor doesn't know how to program in C, or you completely misunderstood what he was saying.
when i went back and further read his notes he sent out i appear to have been way off base on what he said, or he fixed his notes before e-mailing them to us. either way, thank you again for helping to clear that up.
 
Old 07-19-2013, 12:36 AM   #5
Beryllos
Member
 
Registered: Apr 2013
Location: Massachusetts
Distribution: Debian
Posts: 529

Rep: Reputation: 319Reputation: 319Reputation: 319Reputation: 319
I am jumping into this conversation late, but perhaps I can be of assistance. You were off to a good start with the original program (post #1). Could we go back to that? Here are the problems that I can see (though there may be others):
  • It started out using LG, then switches to using *PLG in the loop, but the two were never associated
  • The test is backwards, as ntubski wrote in post #3
  • It needs to use fabs(), also noted by ntubski in post #3
Did the instructor say you have to use a pointer for LG? We can make it work with pointers, but it would be pretty simple to do the whole thing without pointers. What is required here?


By the way, there's nothing wrong with using a do-while loop, as in your post #4. We can make that work, but I just wasn't sure why you dropped the original program using the while loop. The for loop, as in post #2, would not be my first (or second) choice for this kind of problem, though I suppose it could be made to work.
 
1 members found this post helpful.
Old 07-19-2013, 07:56 AM   #6
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by lleb View Post
now if i follow what you said even though NG is now assigned a value, because i am setting the new value of NG before i run my test it will always fail, or never become false. if i leave out the LG = NG in the above do while loop it fails to get past the first loop and prints out the wrong value.

That is where im stuck. do i need additional variables? i am just not seeing how i can update the value of LG with the results of NG if the condition is not met without putting it in the do section of the loop.
Think about the order of the statements in the loop.
 
1 members found this post helpful.
Old 07-19-2013, 02:37 PM   #7
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora/Pop!_OS
Posts: 2,983

Original Poster
Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
Thank you I figured out today after class and talking with both prof and an other student what i needed to fix. here is the working completed code.

1. to solve my issue of updating LG with the value of NG i used something we went over in class with pointers for swapping values of variables.

2. As I am using a do while loop my test was backwards. I forgot that in a do while will continue until the results is false, not true like in a for and an if statement.

Code:
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<math.h>

//user defined function prototype
void swap(double *a, double *b);

int main(void)
{
	double N, NG, LG, *a, *b, epsilon;	// setting all variables to type double

	epsilon = 0.005;			// setting error tolerance to 0.005
	LG = 1.0;				// setting initial guess value

	printf("\nPlease enter the number you wish to find the approximate square root: ");
	scanf("%lf",&N);	// getting input from user

	NG = 0.5 * (LG + (N / LG));	// initialize NG for test in do while loop

do	{
	swap(&NG, &LG);
	NG = 0.5 * (LG + (N / LG));
	printf("\n%.2lf      %.3lf\n", N, NG);
	}	
	while (fabs(LG - NG) >= epsilon);

	printf("\nThe approximate square root of %.2lf is %.3lf\n", N, NG);
}

// using this to swap the values of LG and NG for my do while loop to allow for the update
// of LG from the calculation of NG = foo

void swap(double *a, double *b)
{
	double temp;
	temp = *a;
	*a = *b;
	*b = temp;
	printf("swap number %.2lf", temp);	// used this for testing and troubleshooing logic in do while loop
}
tah dah, it works.

Thank you for the great help.
 
Old 07-20-2013, 02:28 AM   #8
Beryllos
Member
 
Registered: Apr 2013
Location: Massachusetts
Distribution: Debian
Posts: 529

Rep: Reputation: 319Reputation: 319Reputation: 319Reputation: 319
Quote:
Originally Posted by lleb View Post
... tah dah, it works.

Thank you for the great help.
It's good to hear that.

Would you be interested in suggestions for small improvements, or are you done with this?
 
Old 07-20-2013, 10:05 AM   #9
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by lleb View Post
2. As I am using a do while loop my test was backwards. I forgot that in a do while will continue until the results is false, not true like in a for and an if statement.
A for loop also continues until the test is false, the thing that makes a do while different is that it always executes at least one iteration before testing, whereas a for loop might perform zero iterations.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
how to loop over text file lines within bash script for loop? johnpaulodonnell Linux - Newbie 9 07-28-2015 03:49 PM
[SOLVED] Freeing pointers to pointers devnull10 Programming 24 07-26-2012 04:58 AM
[SOLVED] Bash - While Loop reading from two lists simultaneously - nested while loop wolverene13 Programming 11 10-01-2011 05:00 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:30 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration