Failure analysis of newton raphson method says that "For some functions, some starting points may enter an infinite cycle, preventing convergence". I want to keep a check within the program whether it is entering into an infinite cycle or not using assert statement. If it enters then the program will terminate saying convergence is not possible using this initial guess. How can I detect this cycle within the program?
Code:
int user_power, i=0, cnt=0, flag=0;
int coef[10]={0};
float x1=0, x2=0, t=0;
float fx1=0, fdx1=0;
void main()
{
printf("\n\n\t\t\t PROGRAM FOR NEWTON RAPHSON GENERAL");
printf("\n\n\n\tENTER THE MAXIMUM POWER:");
scanf("%d",&user_power);
for(i=0;i<=user_power;i++)
{
printf("\n\t x^%d:",i);
scanf("%d",&coef[i]);
}
printf("\n");
printf("\n\tINTIAL X1---->");
scanf("%f",&x1);
printf("\n ******************************************************");
printf("\n ITERATION X1 FX1 F'X1 ");
printf("\n **********************************************************");
do
{
cnt++;
fx1=fdx1=0;
for(i=user_power;i>=1;i--)
{
fx1+=coef[i] * (pow(x1,i)) ; //calculating f(x1)
}
fx1+=coef[0];
for(i=user_power;i>=0;i--)
{
fdx1+=coef[i]* (i*pow(x1,(i-1))); //calculating f'(x1)
}
t=x2;
assert(fdx1!=0);
x2=(x1-(fx1/fdx1));
x1=x2;
printf("\n %d %.3f %.3f %.3f ",cnt,x2,fx1,fdx1);
} while((fabs(t - x1))>=0.0001);
printf("\n\t THE ROOT OF EQUATION IS %f",x2);
printf("\n");
}
You don't check for periodic orbits. Determining the period and then convergence to the orbit is too expensive.
What you can do is to check after 5 Newton iterations if the condition for quadratic convergence is approximately satisfied. For that you check over 3 steps if the decrease of the function value is more than by a divisor of 4 (or in the step length of the Newton step, it should be more than a divisor of 2).
Failing that, restart with some (random) modification of the initial point.
For most problems, the application of Newton's method in double precision has 2-3 steps of global orientation and then 4-6 steps of quadratic convergence before the precision of the double floating point format is exceeded. Thus, one can be even bolder, if after 10 steps the iteration does not converge, the initial point was bad, be it that it leads to a periodic orbit or divergence to infinity. Most likely, close-by initial points will behave similarly, so make a non-trivial change in the initial point for the start of the next run of the iteration.
Additional remarks:
Investigate the Horner scheme and the double Horner scheme for the evaluation of polynomials (and their derivatives). The use of the power function is ill-advised.
Spend some thought on the situation that there might be no real roots of the polynomial.
For a general idea on finding all roots of a polynomial via Newtons method, see J. H. Hubbard, D. Schleicher, S. Sutherland: How to Find All Roots of Complex Polynomials by Newton's Method, Inventiones Mathematicae vol. 146 (2001) - with a discussion of the global structure of Newton fractals
Related
I was making a little program to test floats in the C: The program itself is very simple, I just want to based on the User's input, return how much Dollar(s), Quarter(s)... etc, his number has.
//------------------------------> First Part: All the necessary Variables <-----------------------------
int main (void)
{
//Getting the user Input
float number = get_float("Number: ");
//Checking if is a positive number
if (number < 0)
{
printf("A positive number, Please: ");
}
//Declaring my Constant/Temporary variables.
float coinValues[] = {1.00, 0.25, 0.10, 0.5, 0.01};
char *coinNames[] = {"Dollar(s): ", "Quarter(s): ", "Dime(s): ", "Nickel(s): ", "Penny(ies): "};
int i = 0;
int tmp = 0;
//-----------------------------------> Second Part: The code Itself <-----------------------------------
//Checking/Printing the necessary coins.
while (number > 0)
{
//Until the loop stops, check if the number can be divided by the CoinValue.
if (number >= coinValues[i])
{
//Print the current Coin Name from the divided value.
printf("%s", coinNames[i]);
//Check if the Current Number still contains Coin Values inside of it, if True counts one in your "Coin Score".
while (number >= coinValues[i])
{
number -= coinValues[i];
tmp++;
}
//Print the Current "Coin Score", then resets TMP.
printf("%i\n", tmp);
tmp = 0;
}
else
{
//Updating the Coin value
i++;
}
}
}
My program was running very well as long I use Integers, but when I converted this code for Floats the values (Dime(s), Nickel(s), and Penny(ies)) start to return non-expected results in the Int variable tmp.
An expected result for a number like 2.6, will be 2 Dollars, 2 Quarters, and 1 Dime, but sometimes, instead of use the Dime(s), the program skips them entire and make the operation with the Nickel(s), however, what is bugging me is that the program is always returning AWL=+ without any value and then the program stay froze forever.
Considering that my only thought is that I'm "suffering" from Float Imprecision, and I don't know how to solve it, so can anyone Help me?
Ps. The program needs to always return the maximum value from each coin before pass forward.
Floating-point arithmetic is designed to approximate real-number arithmetic. IEEE 754-2008 says “Floating-point arithmetic is a systematic approximation of real arithmetic…” So there is no way to “lock” decimal digits in binary floating-point. It is intended to be used where you want an approximation, such as modeling physics. That even includes some financial applications, such as options evaluation. Although floating-point arithmetic can be used for exact calculations in some situations, these require particular care and are generally only pursued in special circumstances.
So the answer to your question on how to lock decimal places is there is no good way to do that with binary floating-point. Attempting to do so generally just yields the same effects as integer arithmetic but less efficiently and with more difficult code. So use integer arithmetic and scale the amounts according to the smallest unit of currency desired, such as a penny.
So as part of a computer science course I've been doing a little bit of C. One of the challenges was to create a program that would tell a hypothetical cashier how many coins they would need in order to give change to a customer. I accomplished this with a set of while loops, the entire program looking like this:
#include <stdio.h>
#include <cs50.h>
int main(void)
{
float f;
int i;
i=0;
do
{
f = get_float("Input Change: \n");
}
while(f<0);
// This do-while loop uses a get_float operator to get a postive input from the user.
while(f>=0.25)
{
f=f-0.25;
i=i+1;
}
// Each one of these loops represents using one kind of coin. For this one, every time it runs it adds
// one coin to the final tally and removes 25 cents from the change owed.
while(f>=0.10)
{
f=f-0.10;
i=i+1;
}
// Dime loop, subtracts ten from change owed.
while(f>=0.05)
{
f=f-0.0500000;
i=i+1;
}
// Nickel loop, subtracts five from change owed.
while(f>0)
{
f=f-0.01;
i=i+1;
}
// Penny loop, subtracts one from change owed.
printf("You need %i coins.%f\n", i, f);
//This just prints the number of coins needed.
}
The issue is that the last while loop we execute randomly even when there is no reason to do so. For example, $0.42 returns a correct value while $0.15 causes the last while loop to add an extra penny for no reason.
while(f>0)
{
f=f-0.01;
i=i+1;
}
(The problematic while loop in question)
I'm new to programming in general, so this is probably just a problem borne of me doing something stupid, but exactly what I'm doing wrong I do not know. Anyone encountered this before?
It's a precision problem. Equality with floats can be rather problematic. Even though in theory f=0 when you get to the last loop, this fails, and it enters the loop.
A possible workaround is to change it to some number between 0 and 0.01. E.g.
while(f>0.005)
But a better approach would be to use type int to represent money, each unit corresponding to a cent.
With floating point values it gets "weird" comparing them to other floats, like 5, 0.63, and 0.0 because your value may actually be 0.4999999999 or 0.000000000001, which is essentially zero, and in your case fails the condition test and thus adds a final penny when the value then truly goes negative. When comparing floats you must account for this by comparing the difference to some small epsilon value.
float epsilon = 0.0000001;
if ((f - testVal) < epsilon) {
...
}
I am working on a very typical university homework. Im supposed to write a C program to estimate the pi via Buffon Needle using Monte Carlo method. I think my program works properly, but i never ever get the pi right. It is always near typical 3.14, but sometimes its 3,148910 sometimes 3,13894. Whats the reason behind it? Can i do anything to make it more 'equal' to accurate value?
(code comments are in Polish, comments in () are in English.)
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
srand(time(NULL));
int i; //wprowadzenie licznika (counter)
double l; // dlugosc igly (lenght of needle)
double n;// liczba prob (number of trials)
double L; // szerokosc miedzy liniami (width between lines)
double x; // kat miedzy igla a normalna do linii (angle)
double pi; // szacowana wartosc liczby pi (pi)
double P=0; //ilość prób spełniających warunek styku igły z linią (ammount of trials that worked)
double d; //odleglosc srodka igly od linii (distance between centre of needle and line)
double y; //minimalizacja obliczeń
double stosun; //stosunek wykonanych obliczeń (ammount of trials to ammount of succesfull trials)
printf("Program szacuje wartosc liczby pi metoda Monte Carlo na podstawie Igly Buffona. Prosze Pamietac o:\n-Podaniu liczby prób jako wartości większej od zera i całkowitej\n-Podaniu długości igły mniejszej niż szerokości między liniami\n");
printf("Prosze podac liczbe prob:\n");
scanf("%lf", &n);
printf("Prosze podac dlugosc igly:\n");
scanf( "%lf", &l);
printf("Prosze podac szerokość miedzy liniami:\n");
scanf("%lf", &L);
if (n <= 0.0 || l > L)
{
printf("Nastąpił błąd wynikających z podania niepoprawnych danych\n");
return 1;
}
printf("%f %f %f", n,l,L); //debuging midway
for (i=0; i<n; i++)
{
x = ((double)rand()/RAND_MAX)*3.1415; // losowy kat w radianach (random angle in radians)
d = ((double)rand()/RAND_MAX)*L/2; // losowa dlugosc igly mniejsza niz odstep miedzy liniami (random needle lenght)
y = (l/2) * sin (x);
printf("Próba%d\n", i);
if (d<=y)
{
P++;
}
}
stosun=n/P;
printf("Stosun %lf", stosun);
pi=stosun*2*l/L;
printf("liczba pi=%lf", pi);
return 0;
}
The variance of Monte Carlo simulations tends to be really large. (They converge to zero error as n increases, but very slowly.) You can read about Buffon's Needle in particular here. I'd like to draw your attention to the figure where 5 different runs of 1000 tosses each are plotted. Inspecting each of them it would look like the value has already converged but to quite a wrong (and different in each case) result.
It's good to do your analysis before you start. The error estimate done rigorously in the above source is about 5.6 / n. That's the variance, so to get a standard deviation, we need a square root, which makes it even worse. After 1000 tosses you can expect π to have an error of about 0.073 (although this can easily be twice as high, or much less, just by pure chance). After a million tosses it should be correct to about ±0.002. After a hundred million you are likely to get the first three digits after the decimal point right and the first error on the fourth or (rarely) fifth. I don't know your n but the values you are getting seem well within what is typical. Edit: with n = 1,000,000, they are +3 σ and –1 σ.
Note that it's a common misconception that one can work around this by making several runs and averaging their results (which should fluctuate above and below the correct value with the same probability, after all). This of course works, but does not offer any advantage whatsoever, apart from the obvious that it can be distributed to multiple machines. The error of running 100 simulations of a thousand iterations each is exactly the same as that of running a single one with a hundred thousand iterations.
An obvious way of making the estimate better is thus increasing the number of hits. One big advantage of Monte Carlo methods is that the individual samples are usually completely independent from each other and thus allow great opportunities for parallelization (OpenMP, vectorized instructions, GPU). But the first step really should be trying to make your code run faster so that increasing n by an order of magnitude or so hurts less. For example, because you know from the analysis that the precision is never going to be really stunning, you can use float instead of double which is on some platforms up to twice as fast. Eliminate the call to sin (it's certainly more elegant if you don't need the value of π to start with). Output your summary only every 1000 steps or so.
A less obvious one is doing the analysis properly and noting how you can decrease the numerator in the variance (the denominator will be n anything you do). If I am not mistaken this experiment runs the best when the length of the needle is equal to the separation between the lines: less than that is suboptimal and more than that brings multiple crossings which you don't want. There may be other ways of how to enhance it by altering the distribution of the angle and/or the position.
I'm trying to write a code that asks from the user to give 5 coefficients for a 5th-degree polynomial, and it also asks to give a range (two values) that the programs checks if there is a solution in it or not (I'm asked to find only one), and the solution must be an integer, while the coefficients can be floats.
I'm thinking of writing a code that runs over every integer in the range and substitute it in a description of a polynomial than I define, and check if its equal to zero, but I got stuck at deciding how to make the loops.
And another thing, if there are more than one root in the interval that the user enters, then we must print the minimal value of the roots (but I have no direction how to do that either).
I will show you what I wrote so far, and any kind of help would be appreciated:
#include <stdio.h>
#define zero 0.00001
int main()
{
double a, b, c , d , e , f , y , beginning_of_range, end_of_range;
int x;
printf("please enter the coefficients of the polynomial:\n");
scanf("%lf%lf%lf%lf%lf", &a, &b, &c, &d, &e);
printf("please enter two values to indicate the beginning and end of range:\n");
scanf("%lf%lf", &beginning_of_range, &end_of_range);
while (beginning_of_range > end_of_range)
{
printf("ERROR: the range you have entered isn't valid, please try again:");
scanf("%lf%lf", &beginning_of_range, &end_of_range);
}
while (beginning_of_range < end_of_range)
{
x = beginning_of_range;
y = a + b*x + c*x*x + d*x*x*x + e*x*x*x*x + f*x*x*x*x*x;
if (y == zero)
{
printf("the root is:%d", x);
}
else
{
x = x+1;
}
break;
}
return 0;
}
Your task as written is very questionable, so much so that there is perhaps a mis-interpretation or mis-communication.
A randomly given polynomial with floating point coefficients will have integer roots with probability so close to zero that it is practically impossible.
Even with integer coefficients it requires carefully reverse-engineered coefficients to get an integer root. Just change one coefficient by one and in most cases all roots will be irrational.
What you can do in your framework is to find intervals with a sign change so that there is at least one root inside the interval that can be found using one of bisection, regula falsi, Illinois, secant or Mullers methods. All of them derivative free.
Without identifying all roots, also the complex ones, it is rather hard to guarantee that all real roots have been found. Thus it is only approximately possible to find the smallest real root inside the given interval. There might be an integer interval with two real roots inside so that at the boundaries the sign is the same. You would have to analyse the signs of all derivatives at the integer points to make more reliable guesses in this case, see Descartes rule and Budan-Fourier theorem.
Your first while loop should probably be an if statement instead of a loop.
Your second (main) while loop never increments the beginning of range. This is probably causing an endless loop for you.
I'm quite a beginner in this topic, and couldn't find out the reason: sometimes the program works, sometimes not (after asking the question, it simply doensn't want to take in my answers, than I can write in as much as I want, it doesn't respond, just list out the numbers, I tiped in)
#include <stdio.h>
float abszolut (float szam)
{
float abszoluterteke;
if (szam >=0)
abszoluterteke = szam;
else
abszoluterteke = -szam;
return abszoluterteke;
}
float negyzetgyok (float szam)
{
float pontossag = 0.000001;
float tipp = 1;
if (szam <0)
{
printf ("Megszakítás elfogadva! \nKöszönjük, hogy programunkat választotta!\n");
return -1;
}
else
{while (abszolut (tipp*tipp-szam) >= pontossag)
tipp = (szam/tipp + tipp)/2;
return tipp;
}
}
int main (void)
{
float alap, eredmeny;
for (;;)
{
printf ("Melyik számnak szeretnéd meghatározni a négyzetgyökét ilyen módszerrel?\n");
scanf ("%f", &alap);
eredmeny = negyzetgyok (alap);
if (eredmeny == -1)
return 1;
else
printf ("A(z) %f négyzetgyöke megfelelő közelítéssel: %f\n", alap, eredmeny);
}
return 0;
}
Change for abszolut (tipp*tipp-szam) >= pontossag*szam
The while loop must stop once tipp*tipp is close to szam. But IEEE floating point computations have a limited precision : about 7 digits for float and 15 digits for double.
So the error on float szam is about 0.0000001*szam. It's the same for tipp. Consequently, the error on tipp*tipp-szam is higher than 0.0000001*szam. If szam is large, this error will hardly become lower than 0.000001. Even if double precision is used, it is likely that while (abszolut (tipp*tipp-szam) >= pontossag) triggers an infinite loop for very large numbers.
On the other side, what happens if szam is very small, say 1e-10 ? The while loop prematurely exits and the square root of 1e-10 is computed as something about 1e-3, instead of 1e-5... The relative error is about 10000%... And using double does not change anything !
To avoid this, you can change for abszolut (tipp*tipp-szam) >= pontossag*szam.
Notice that both sides have the same dimension. If szam were in square feet, tipp would be in feet and pontossag, the precision, is dimensionless. It is a good practice to compare things having the same dimension.
If you keep noticing infinite loops, switch to double precision or increase pontossag.
To avoid infinite loop, add a counter int i; and exit the while loop if the number of iteration is 100. 100 should be sufficient, since your Newton-Raphson iteration features a quadratic convergence.
There are a number of problems with your code.
The exit condition in your loop is flawed.
The problem with your square root algorithm is the use of the error limit pontossag. Your algorithm will give erroneous results for very small numbers and it will loop forever for numbers larger than 20 or so. To fix this, change the loop test from abszolut (tipp*tipp-szam) >= pontossag to abszolut (tipp*tipp-szam) >= pontossag*szam.
You aren't checking for all the problem cases.
If your computer uses IEEE 754 floating point, your algorithm happens to work. That's just luck. Never rely on luck when doing numerical programming. It's easy to input an infinity. For example, 3.5e38 (350000000000000000000000000000000000000) does the trick with single precision numbers (float). Your function negyzetgyok should check for infinity:
if (isinf (szam))
{
return szam;
}
You can do much better than an initial guess of 1.0 as the square root.
An initial guess of 1.0 against 3.4e38 means a lot of needless looping. A fast and easy way to form a good initial guess is to take advantage of the fact that floating point numbers are represented internally as (1+fractional_part)*2^exponent. A good first guess is 1*2^(exponent/2). With single precision numbers,
int expo;
float tipp;
frexpf (szam, &expo);
tipp = ldexpf (1.0f, n/2);
You are using %f rather than %g to parse floating point numbers.
The %g format can parse anything that can be parsed with the %f format, plus a whole lot more.
You aren't checking the status of fscanf.
Enter x when prompted to enter a number. The scanner will read that character, which stops the scan. The scanner will put that character (x) back into the input buffer, and return 0, indicating that nothing was scanned. The next time around, the scanner will read the character x again, once again put that character back into the input buffer, and once again return 0. Infinite loop! Always check the status of any of the scanf family of functions to see if the scanner scanned the number of items expected.
You are using fscanf.
There are a number of existing questions and answers at this site that address the many problems with using fscanf to read from a file. This is particularly so when reading human-generated input. People make mistakes. Ignoring that people do make mistakes on entering data is a programming error. A better approach would be to read a line into a buffer using frets and parse that line with sscanf.