I'm working in a simple program that calculates the root of any given function using Newton-Raphson's method. In this program I have to print the found root and the number of iterations made. The program itself is fine, I can find the root of any given function but I can't count properly the number of iterations. It is always 5 over the max. number of iterations or 1 less than it. Here's the code in C++:
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
double f(float x)
{
double function1;
function1 = exp(x)- 4*pow(x,2); // given function
return function1;
}
double derivative(float x)
{
double derivative1;
derivative1 = exp(x) - 8*x; // derivative of given function
return derivative1;
}
void newtonMethod(double x0, double error, int N)
{
double xNext, xPrevious, root;
int k;
xPrevious = x0;
for(int i = 0; i < N || f(xNext) > error; i++)
{
xNext = xPrevious - (f(xPrevious)/derivative(xPrevious)); // calculates the next value of x
xPrevious = xNext;
root = xNext;
k = i;
}
cout << endl;
cout << "Iterations made: " << k << endl;
cout << endl;
cout << endl;
cout << endl;
cout << "Root is: " << root << endl;
}
int main()
{
double x0, error;
int N; // max. number of iterations you can do
cout << "Enter x0: ";
cin >> x0;
cout << "Enter the error: ";
cin >> error;
cout << "Enter the max. number of iterations: ";
cin >> N;
newtonMethod(x0, error, N);
}
And I'm pretty sure the error is in this piece of code:
;i < N || f(xNext) > error;
If I run this program and put N = 100, it shows the right root but it prints "Iterations made = 99" but this is wrong. What do I do to print the right number of iterations made? For example, for the function in the program above (e^x - 4x²) it should stop in the fourth iteration if I enter x0 = 0.5 and error = 0.0001. How to fix it?
To answer your question, which was why the following piece of code does not work:
;i < N || f(xNext) > error;
It is simply because that, in a for loop condition, it is a continuing condition that is evaluated, and not a stopping condition.
In the above piece of code, what you are telling the compiler is: continue the loop as long as either i < N is true or f(xNext) > error is true. Therefore, when you input x0 = 0.5, error = 0.0001 and N = 100, what the loop does is that it will not stop until both criteria are false, i.e. when i reaches N AND the tolerance in f(x) is smaller than error.
Now, the solution is simply to swap the || operator to && operator. Like this:
i < N && f(xNext) > error;
but then, your xNext is not initialized. Because that your xNext and xPrevious are equal at the end of each loop, I would simply put xPrevious instead. In addition, as #Rathat has written, evaluating your tolerance in f(x) should take its absolute value, so:
i < N && abs(f(xPrevious)) > error;
Finally, you should output the number of iterations as k + 1 since you started with i = 0.
This should solve your problem.
thanks for all the answers. I found out what's wrong besides the logic behind the for condition that #yuxiangDev explained very well. Despite #RatHat code being totally right the error was in the math.h library I was using. I tried with <cmath> and it worked really well! lol.
Related
I wrote a program to sum all odd numbers less than or equal to N. It's not the most efficient or eloquent program, but it works in the compiler on Codepad.org and does not work in DevC++. Usually when a program I wrote is stuck in some kind of infinite loop the program crashes in DevC++ and Windows stops it and lets me know.
Here, the program compiles and runs, but just sits with the cursor blinking and does nothing. Windows doesn't stop it, nothing happens, the program doesn't finish, no matter for how long I let it sit. I'm guessing this is a problem with DevC++ unless it's a problem with my code that Codepad overlooks. Will anyone explain to me what is happening here?
Here is my code:
#include <iostream>
using namespace std;
int odd(int N)
{
int i;
int sum = 0;
for(i = 0; i <= N; ++i)
{
while((i % 2) != 0)
{
sum = sum + i;
}
}
return sum;
}
int main()
{
int N;
cout << "Pick a value: ";
cin >> N;
cout << "The sum of all numbers <= to " << N << " is: " << odd(N);
return 0;
}
I've made the suggested change to an if-statement and the same problem is occuring:
#include <iostream>
using namespace std;
int odd(int N)
{
int i;
int sum = 0;
for(i = 0; i <= N; ++i)
{
if ((i % 2) != 0)
{
sum = sum + i;
}
}
return sum;
}
int main()
{
int N;
cout << "Pick a value: ";
cin >> N;
cout << "The sum of all odd numbers <= to " << N << " is: " << odd(N);
return 0;
}
while((i % 2) != 0)
{
sum = sum + i;
}
This is a infinite loop.Because if (i % 2 != 0) is true then the program will increment sum again and again.What you are probably looking to do is have an if statement instead of while
Seems like the edit is working, please try deleting the old output file and rebuilding and re-compile the entire program.
The output seems to be as follows:
Pick a value: 52
The sum of all odd numbers <= to 52 is: 676
Process exited after 1.034 seconds with return value 0
Press any key to continue . . .
make sure the window of the previous run is closed else the compiler will not recompile but just runs the previous version before you changed it.you may see this as an error stated at bottom in debug mode.
the while() is an infinite loop because i is not changed inside the while() or its {} so use if
I'm having trouble giving the user an option to loop a loop. This program works fine
#include <iostream>
using namespace std;
int main()
{
// goal is to calculate the sum of the first 10 terms of Leibniz's Series....
// calculated by 1 - 1/3 + 1/5 - 1/7 + 1/9 ..... - 1/19
int termNumber; // keeps track of term numbers
int numberOfTerms = 0;
cout << "Enter number of Terms";
cin >> numberOfTerms;
double sum = 0.0;
int sign = +1;
for (termNumber = 1; termNumber <= numberOfTerms; termNumber++)
{
sum += ( sign / (2.0 * termNumber - 1));
sign *= -1;
}
cout << "\n\n The sum is " << ( 4 * sum) << "\n\n";
} // end body of loop
I need to give the user an option to repeat the program if he would like so I thought I could put it in a do-while loop, but when I do that it only loops "enter number of terms" any way I try to format it. This is the best I have at the moment.
#include <iostream>
using namespace std;
int main()
{
// goal is to calculate the sum of the first 10 terms of Leibniz's Series....
// calculated by 1 - 1/3 + 1/5 - 1/7 + 1/9 ..... - 1/19
cout << "\nGiven a positive integer specifying some number of terms, this program\n approximates "
"pi using Leibniz' Formula and the given number of terms.\n\n" ;
cout << "Leibniz' formula is 1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 + ... = Pi / 4.\n\n";
char yes = 0;
double sum = 0.0;
do {
int termNumber; // keeps track of term numbers
int numberOfTerms = 0;
int sign = +1;
cout << "enter number of terms.\n";
cin >> numberOfTerms;
for (termNumber = 1; termNumber <= numberOfTerms; termNumber++)
{
sum += (sign / (2.0 * termNumber - 1));
sign *= -1;
}
}
while (yes = 1);
cout << "\n\n The sum is " << (4 * sum) << "\n\n";
cout << "would you like to go again? " << yes;
} // end body of loop
I would like to give them the option to try a different amount using term numbers where y/Y and n/N work.
Thanks for any help I may get.
You need a cin to set yes and your cout lines are in the wrong place. They need to be inside of your do while loop. And an == in your while
do {
int termNumber; // keeps track of term numbers
int numberOfTerms = 0;
int sign = +1;
cout << "enter number of terms.\n";
cin >> numberOfTerms;
for (termNumber = 1; termNumber <= numberOfTerms; termNumber++)
{
sum += (sign / (2.0 * termNumber - 1));
sign *= -1;
}
cout << "\n\n The sum is " << (4 * sum) << "\n\n";
cout << "would you like to go again? " << yes;
cin >> yes
}
while (yes == 1);
try that
Just my two cents but maybe you can combine both of your ideas and use functions. Put the code you have in the do part above into a function with a parameter of number of terms. Also use your for loop in the body of this function. Then on the outside of your for loop call another function that asks the user if they would like to continue and also ask a new number for the "terms" and pass that back into the first function if the user supplies a 'y' or 'Y' else if a 'n' or 'N' you can just stop the program
Have you learned to use
continue;
in a for loop? I think this fits your description, basically what
continue;
does is it returns to the beginning of the for-loop in this case in a certain scenario.
The problem with the do while loop is that the variable used in the while() statement must have been defined outside of the loop body, even though syntactically is belongs to the loop. This can be avoided when using a for loop instead, which allows the definition of such variables within the for statement. Here is an example.
inline double leibniz (int n) noexcept // function for Leibniz sum
{
double result=0;
for(int k=1,sign=1; n; --n,++++k,sign=-sign)
result += double(sign)/double(k);
return result;
};
int main()
{
// no loose variables defined outside loop
for(bool again=true; again; ) { // control variable only lives withing loop body
int n; // number of terms, only needed within loop body
std::cout<<"number of terms = ";
std::cin >> n;
std::cout<<"result = "<<leibniz(n)<<'\n'
<<"try again? (1/0)";
std::cin >>again;
}
}
Thanks everyone for the help.
I didn't know the continue; yet, but I learned about it.
The major problem was my cin and cout were not in the right spot like stated before. Redid the last line to while (yes == 'Y' || yes == 'y'); and now all works perfectly.
You guys are great!
I have thoroughly searched for this topic all over the internet, and the threads are either dead, or use a different method than what is described in my book.
For example, http://www.geeksforgeeks.org/square-root-of-a-perfect-square/ . This doesn't work for me because my algorithm needs to loop until it reaches 1% of the last "guess".
Here is the question from the text.
The Babylonian algorithm to compute the square root of a number n is as follows:
Make a guess at the number (you can pick n/2 as your initial guess).
Compute r = n / guess
Set guess = (guess + r) / 2
Go back to step 2 for as many iterations as necessary. The more that steps 2 and 3 are repeated, the closer guess will become to the
square root of n.
Write a program that inputs an integer for n, iterates through the
Babylonian algorithm until guess is within 1% of the previous guess,
and outputs the answer as a double.
I have written the following code:
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
int n;
double r, guess(4), lastGuess;
cout << "Enter a number to find the square root of: ";
cin >> n;
do
{
r = n / guess;
lastGuess = guess;
guess = ( guess + r ) / 2;
// cout <<"Guess: " << guess << endl;
// cout <<"Last Guess: " << lastGuess << endl;
cout << "Guess : " << guess << endl;
cout << "Last Guess 1% = " << lastGuess + ( lastGuess * 0.01 ) << endl;
cout << "r = " << r << endl;
} while( guess >= lastGuess * 0.01 );
cout << r;
return 0;
}
The program computes the right answer for r, but the loop doesn't terminate despite guess being greater than 1% added to lastGuess.
This program produces the following output when inputting 144 as n.
....
r = 12
Guess : 12
Last Guess 1% = 12.12
r = 12
Guess : 12
Last Guess 1% = 12.12
r = 12
Guess : 12
Last Guess 1% = 12.12
r = 12
Guess : 12
Last Guess 1% = 12.12
....
The root (r) is correct (12). The guess is LESS than lastGuess (12 < 12.12), which should return a false to the condition, correct?. Why is the loop not ending?
If you want to add 1% you need to multiply by 1.01, not 0.01.
while( guess >= lastGuess * 1.01 );
By the way, this iterates while guess is growing by more than 1%. You should also allow for the opposite, that it may have shrunk by more than 1%. The approximation could approach the answer from either direction. (It will approach positive roots from the right and negative roots from the left.)
While printing your lastGuess you are using
lastGuess + ( lastGuess * 0.01 )
But while checking loop condition you are using
lastGuess*0.01
So in loop condition use the same equation which you are using for printing lastGuess value.
To properly exit the loop, use something similar to this.
void f(int N)
{
double x = N / 4;
double prev = 0.0f;
while(1)
{
x = 0.5 * (x + N / x);
if (prev == x)
break;
prev = x;
printf("val: %f\n", x);
}
printf("SQRT(%d) = %f\n", N, x);
}
I had the same problem in my book. This is what I wrote and it works perfect.
#include <iostream>
using namespace std;
int main()
{
double guess, root, previousGuess;
int number;
cout << "Enter a number to find the Babylonian square root.\n";
cin >> number;
cout << "You want to find the square root of " << number << ".\n";
cout << "Enter a guess for the square root.\n";
cin >> guess;
do
{
root = number / guess;
previousGuess = guess;
guess = (guess + root ) / 2;
} while(guess < 0.99*previousGuess || guess > 1.01*previousGuess);
cout << "The answer is " << guess << ".\n";
return 0;
}
I am trying to write a code that finds perfect numbers lower than the user's input.
Sample of correct output:
Enter a positive integer: 100
6 is a perfect number
28 is a perfect number
There are no more perfect numbers less than or equal to 100
But when I run my code, I get the error Floating point exception
and can not figure out why. What am I doing wrong?
Here is my code:
#include <iostream>
using namespace std;
bool isAFactor(int, int);
int main(){
int x, y;
int countOut, countIn;
int userIn;
int perfect = 0;
cout << "Enter a positive integer: ";
cin >> userIn;
for(countOut = 0; countOut < userIn; countOut++){
for(countIn = 1; countIn <= countOut; countIn++){
if(isAFactor(countOut, countIn) == true){
countOut = countOut + perfect;
}
}
if(perfect == countOut){
cout << perfect << " is a perfect number" << endl;
}
perfect++;
}
cout << "There are no more perfect numbers less than or equal to " << userIn << endl;
return 0;
}
bool isAFactor(int inner, int outer){
if(outer % inner == 0){
return true;
}
else{
return false;
}
}
The arguments are just swapped. You are calling the function as isAFactor(countOut, countIn) when you should be calling with isAFactor(countIn, countOut)
To clarify #Aki Suihkonen's comment, when performing:
outer % inner
If inner is zero, you will get a divide by zero error.
This can be traced backward by calling isAFactor(0, 1).
It is in your for loop in main.
The first parameter to isAFactor(countOut, countIn) is assigned in the outermost for loop:
for (countOut = 0; ...
Notice the value you are initializing countOut with.
Edit 1:
Change your `isAFactor` function to:
if (inner == 0)
{
cerr << "Divide by zero.\n";
cerr.flush();
return 0;
}
if (outer % inner ...
Place a breakpoint at either cerr line above.
When the execution stops there, look at the Stack Trace. A good debugger will also allow you to examine the parameter / values at each point in the trace.
I am unsure what the fault in my logic is. Sample output:
How many terms of the Fibonacci Sequence do you wish to compute?
1
1
1
--How many terms of the Fibonacci Sequence do you wish to compute?
5
5
5
5
5
5
5
Why is it doing this?
// Recursive Fibonacci Sequence
#include <iostream>
using namespace std;
double fib(double number);
int main(void) {
double number;
cout << "How many terms of the Fibonacci Sequence do you wish to compute?" << endl;
cin >> number;
for(int i = 0; i <= number; ++i)
cout << fib(number) << endl;
} // end main
// function fib definition
double fib(double number) {
if((number == 0) || (number == 1))
return number;
else
return fib(number - 1) + fib(number - 2);
} // end function fib
Look at your loop:
for(int i = 0; i <= number; ++i)
cout << fib(number) << endl;
Notice how the body of the loop doesn't use i... it always calls fib(number). Changing that to fib(i) will fix it.
(It's not terribly efficient, in that you'll end up recalculating values each time, but that's a separate matter. While you could put the printing in fib, that mixes the concerns of "what to do with the results" and "computing the Fibonacci sequence".)
You should just pass 'i' as the parameter in your for loop not 'number'
Make it:
for(int i = 0; i <= number; ++i)
cout << fib(i) << endl;