C Program gets stuck in an infinite loop - c

The problem I've been having is that my code will get stuck either in an infinite loop or will have a stack overflow problem and begin producing negative numbers during calculations.
I am aware that this issue is coming from my while loop and also think the issue probably lies with the formula I am using being the line i = (r / 12)*(b - p + temp);.
However I am unsure of how to fix this. My formula is trying to calculate the interest paid on a fixed interest loan for each month over 12 months and print that to the screen with the remaining balance. This is supposed to continue until the balance reaches 0.
#include <stdio.h>
// main function
int main()
{
// variable declarations
float r = 0.22; // interest rate
float b = 5000.0; // amount borrowed
float p; // payment amount
int m = 1;
float temp, ti = 0;
float i;
// Take in data from user
printf("Please enter the amount you wish to pay monthly: \n");
scanf("%f", &p);
printf("\n");
//display interest rate, initial balance, monthly payment
printf("r = %.2f\nb = %.1f\np = %.1f \n\n", r, b, p);
// Month by month table showing month interest due/paid and remaining balance
i = (r / 12) * b;
temp = i;
printf("%d %.2f %.2f\n", m,i,b);
m++;
while (i > 0) {
i = (r / 12) * (b - p + temp);
b = (b - p + temp);
ti += temp;
temp = i;
printf("%d %.2f %.2f\n",m, i, b);
m++;
}
printf("\n");
printf("total interest paid: %.2f\n", ti);
return 0;
}

Well, if I'm doing the math correctly it looks like if you enter a value less than 91.67 for P you are going to get stuck in an infinite loop because the monthly payments are less than the interest accusing on the debt; so you might want to add a check for that.
As an aside if you named your variables as Interest, Base, etc. you wouldn't need the comments and the code would be easier to read.
Also since you are printing out the payment info until balance is zero you should loop while b > 0.

The program works as expected.
The only problem is, if your monthly payment are less
than the interest rate - then the amount you need to pay back
grows exponentially and the program never stops.
Enter any number >= 92 and it seems to work.
Is 22% p.a. interest rate correctly?

I don't see this generating an infinite loop but it would become a problem if your repayment is higher than the matured interest, which with your starting parameter it means anything below 91.67.
You may have a wrong end condition so there is always a negative line printed, though.

Related

Converting km to miles, feet, yards and inches (More detailed question below)

#include <stdio.h>
int main(){
double km, miles, yards, feet, inches;
scanf("%lf", &km);
miles = km/1.609;
printf("%d\n", (int)miles);
yards = ((km*1093.61) - ((int)miles*1760));
printf("%d\n", (int)yards);
feet = (km*3281.4) - ((int)miles*5280 + yards*3);
printf("%d\n", (int)feet);
inches = km*39378.498 - ((int)miles*63360 + (int)yards*36 + (int)feet*12);
printf("%.2lf", inches);
return 0;
}
This is what I managed to write, however it still doesn't pass all tests and isn't 100% accurate as seen in the image below
Help would be highly appreciated.
When writing code to do conversions such as in your task, it is better to do all (internal) calculations in double precision and convert each component part of the result (to int) 'on the fly', then subtract each of those converted values as they are determined.
So, first get the conversion into miles as a double value, then subtract each integral part and multiply the remainder by the factor required to get the next sub-unit. Using this approach, you are far less likely to encounter problems due to integer overflow and rounding errors.
The following is a potential solution. (Note that it is far better to write clear code than attempt to 'compress' many operations into single-line code; the latter is a common cause for bugs creeping into your code and also makes it more difficult for future developers of your code to understand and/or modify it.)
#include <stdio.h>
int main()
{
double km = -1.0, total, inches;
int miles, yards, feet;
do {
printf("Enter value in Km: ");
if (scanf("%lf", &km) != 1) { // Error input: clear buffer
int c;
while ((c = getchar()) != '\n' && c != EOF)
;
if (c == EOF) return 1; // Can't do much after an EOF!
}
} while (km < 0.0);
// First, do the conversion to double "total" ...
total = km / 1.609;
// Now, get the integer "miles" value and subtract that from the total ...
miles = (int)total;
total -= (double)miles;
// Next, multiply remainder by 1760 to get the number of yards ...
total *= 1760.0;
// Now, get the integer value and subtract that from total ...
yards = (int)total;
total -= (double)yards;
// Multiply remainder by 3 to get feet ...
total *= 3.0;
feet = (int)total;
total -= (double)feet;
// Finally, multiply remainder by 12 to get inches ...
inches = total * 12.0;
// Display result:
printf("%d %d %d %.2lf\n", miles, yards, feet, inches);
return 0;
}
Note that I have also added some code to check that the input value is 'acceptable' (I have chosen to reject negative values, but you can easily change that condition); more importantly, the code will also be able to deal with situations where the user enters a value that cannot be interpreted as a floating-point input (like "Fred"). When using scanf for user input, it is always a good idea to check for valid input and handle possible error conditions.

C Nested Loop for Interest

My C program has to contain a loop that increases the interest rate, and a nested loop that calculates the interest and displays a total per each interest rate. Can anyone point me in the right direction?
The program should output 10 interest rates and the corresponding total interest plus the loan
The interest rate starts .01 (1 percent) and should end at .10 (10 percent).
#include <stdio.h>
int main(void)
{
double loan = 1000.00, rate = 0.01, output;
int year = 1;
do {
rate + 0.01;
for (year = 1; year < 11; year++) {
output = rate * loan + loan;
}
printf("%d $%d\n", year, output);
} while (year < 11);
return 0;
}
First things first, turn on warnings. C compilers normally don't give you warnings, it's generally -Wall to get the basics (not all). Once we do that...
test.c:17:36: warning: format specifies type 'int' but the argument has type 'double' [-Wformat]
printf("%d $%d\n", year, output);
~~ ^~~~~~
%f
That tells us you're passing a floating point number to printf but trying to treat it as an integer, so it's going to be translated to a string incorrectly. It needs to be.
printf("%d $%.2f\n", year, output);
%f for a floating point number, and the .2 means to only use two decimal places like money.
test.c:9:14: warning: expression result unused [-Wunused-value]
rate + 0.01;
~~~~ ^ ~~~~
2 warnings generated.
This one tells us that the rate is never incremented. It's added to, but never stored anywhere. Instead you want rate += 0.01.
Now it runs. Once. And it only reports on year 11.
The problem is your outer do/while loop is using year, but the for loop will end with the year at the threshhold, so it will immediately stop. Instead of using a do/while loop, which is rarely necessary, use another for loop.
Second problem is you're printing the output and year outside the year for loop. So you'll only ever get the result for the last year. If you want all the years, the print goes inside.
#include <stdio.h>
int main(void)
{
const double initial_loan = 1000.00;
for( double rate = 0.01; rate <= 0.10; rate += 0.01 ) {
double loan = initial_loan;
for (int year = 1; year <= 10; year++) {
loan += rate*loan;
printf("%d # %.2f%% $%.2f\n", year, rate * 100, loan);
}
}
return 0;
}
Notice that I declare variables in the narrowest possible scope. This tells you when they're appropriate to be used, and avoids goofs like trying to use the year in the outer loop.
A lot of C material will be extremely conservative and tell you to declare all variables at the start of a function. This isn't necessary, and hasn't been for a long, long time. Though declaring variables in a for loop is a C99 thing, that part of C99 is very well supported.

Example of a colloquium exam

Check the image
This is my 1st post so have that in mind while reading my question.
I have an exam of a colloquium but my code does not provide me the correct result.
So if anyone could help me that would be great. :)
These are the informations that are provided in the exam:
A function y=f(x)=ax^2+bx+c
We have to find the surface that is below the chart but keep in mind that dx(Delta X)=B-A and the height goes like this: A,A+dx,A+2dx, .... , B-dx.
As dx value gets lower the surface will be more accurate.
You have to write the program so that the surface with precision 0.001
This is my code so could someone who is good in C check it please.
Thank you.
#include <stdio.h>
#include <math.h>
int main()
{
int a,b,c;
double A,B,dx,p,D,q,x,y,nv,nv1,nv2,sv;
do{
printf("Insert a & b: "),scanf("%lf %lf",&A,&B);
} while(A<1 || B<1);
nv=dx=B-A;
do{
printf("enter odds: "),scanf("%d %d %d",&a,&b,&c);
p=(-b)/2;
D=sqrt(pow(b,2)-4*a*c);
q= -D/4*a;
} while( a<0 || p<0 || q<0);
do{
sv=nv;
dx/=2;
nv=0;
for(x=A;x<p;x+=dx)
for(dx=B-A;dx<q;dx/=2)
nv1+=x*dx;
for(y=p;y<=B;y+=dx)
for(dx=q;dx<B;dx/=2)
nv2+=y*dx;
nv=nv1+nv2;
}while(fabs(nv-sv)>0.001);
printf("The surface is %lf",nv);
return 0;
}
You want to find the approximation of a definite integral of a quadratic function. There are several issues with your code:
What is the restriction of A ≥ 1 and B ≥ 1 for? A parabola is defined over the whole abscissa. If anything, you should enforce that the input is numeric and that two values were given.
You don't need to find the vertex of the parabola. Your task is to create small rectangles based on the left x value of each interval as the image shows. Therefore, you don't need p and q. And you shouldn't enforce that the vertex is in the first quadrant on the input without indication.
Why are the coefficients of the parabola integers? Make them doubles to be consistent.
Because you don't need to know the vertex, you don't need to split your loop in two. In your code, you don't even check that p is between A and B, which is a requirement of cour code.
What is the inner loop for? You are supposed to just calculate the area of the current rectangle here. What's worse: you re-use the variable dx as iteration variable, which means you lose it as an indicator of how large your current interval is.
The repeated incrementing of dx may lead to an accumulated floating-point error when the number of intervals is large. A common technique to avoid this is to use an integer variable for loop control and the determine the actual floating-point variable by multiplication.
The absolute value as a convergence criterion may lead to problems with small and big numbers. The iteration ends too early for small values and it may never reach the criterion for big numbers, where a difference of 0.001 cannot be resolved.
Here's a version of your code that puts all that into practice:
#include <stdio.h>
#include <math.h>
int main()
{
double a, b, c;
double A, B;
printf("Lower and upper limit A, B: ");
scanf("%lf %lf", &A, &B);
printf("enter coefficients a, b, c: ");
scanf("%lf %lf %lf", &a, &b, &c);
double nv = 0;
double sv;
int n = 1;
do {
int i;
double dx;
sv = nv;
n *= 2;
dx = (B - A) / n;
nv = 0;
for (i = 0; i < n; i++) {
double x = A + i * (B - A) / n;
double y = a*x*x + b*x + c;
nv += dx * y;
}
} while(fabs(nv - sv) > 0.0005 * fabs(nv + sv));
printf("Surface: %lf\n", nv);
return 0;
}
The code is well-behaved for empty intervals (where A = B) or reversed intervals (where A > B). The inpt is still quick and dirty. It should really heck that the entered values are valid numbers. There's no need to restrict the input arbitrarily, though.

averaging while looping, the sum won't clear and thus keeps adding numbers from previous loop entry

#include <stdio.h>
int main () {
int days, flights, t, b;
float length, mean, sum;
printf("How many days has your dragon been practicing?\n");
scanf("%d", &days);
for(t=1; t<=days; t++) {
printf("How many flights were completed in day #%d?\n", t);
scanf("%d", &flights);
for(b=1; b<=flights; b++) {
printf("How long was flight #%d?\n", b);
scanf("%f", &length);
sum+=length;
}
mean = sum/flights;
printf("Day #%d: The average distance is %.3f.\n", t, mean);
}
}
the sum used to calculate the mean is supposed to be only the number from one iteration of the loop added together. instead the sum used numbers from the new iteration and old iteration added together.
If I understood your problem correctly, after the last printf() statement, you should reset sum to 0, like sum = 0;.
That said, the major issue in your code is that, you're using sum (an automatic storage local variable) while uninitialized. You should be initializing sum to some value (0, maybe) before making use (sum+=) of it. Otherwise, it it invokes undefined behavior.
To quote C11 standard, chapter §6.7.9
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. [...]
sum won't clear because you don't clear it ! The point of writing code is to make your dumb machine(yeah dumb!) know when it's got to do what!
So immediately after
for(t=1;t<=days;t++)
{
Add this:
sum=0;
This will ensure that your sum value is reset every day your dragon takes a flight! Otherwise C will use some random garbage value as your sum and you would receive weird answers!
Some suggestions:
1) If you call scanf() just after you call printf(), there is no reason to use '\n' inside that printf at the end.
2) Always check scanf() for errors or your code is useless if errors occurs.
Now about your code:
When you use something like x+=y this means x = x + y.
So, in your case sum+=length means sum=sum+length. Do you know the value of sum? Yes is a garbage value.
About this line mean = sum/flights;, what is mean, sum and what is flights? Yes, first are float but second is int.
Now putting all together:
#include <stdio.h>
int main (void){
int days, flights, t, b;
float length, mean, sum=0;
printf("How many days has your dragon been practicing?: ");
if((scanf("%d", &days)) != 1){
printf("Error\n");
}
for(t=1; t<=days; t++) {
printf("How many flights were completed in day #%d?: ", t);
if((scanf("%d", &flights)) != 1){
printf("Error\n");
}
for(b=1; b<=flights; b++) {
printf("How long was flight #%d?\n", b);
if((scanf("%f", &length)) != 1){
printf("Error\n");
}
sum+=length;
}
mean = sum/(float)flights;
printf("Day #%d: The average distance is %.3f.\n", t, mean);
}
return 0;
}

Monthly payments C program

Need some help with calculating the fixed monthly payment (P) required to fully amortize a loan of L dollars over a term of n months at a monthly interest rate of i. The given formula is: P = L[i(1 + i)n]/[(1 + i)n - 1]. I wrote a code but it didn't calculate Payment. I'm wondering if it is because I use double type together with int (for number of months) or the problem with formula?! Please help.
#include<stdio.h>
#include <math.h>
double calculatePayments(double rate, double loan, int payments);
int main() {
double principal, i, monthlyP;
int month;
printf ("Enter the principal amount: ");
scanf ("%f", &principal);
printf ("Enter the interest amount: ");
scanf ("%f", &i);
printf ("Enter the term in months: ");
scanf ("%d", &month);
monthlyP = calculatePayments (i, principal, month);
printf ("The monthly payment amount is %.2f: ", monthlyP);
return 0;
}
double calculatePayments(double rate, double loan, int payments) {
double mPayments;
mPayments = loan*(rate*(1 + rate)*payments)/((1 + rate)*payments - 1);
return mPayments;
}
Your scanf() requests %f format for a double; it should be %lf.
In addition to the need to fix the input (%lf instead of %f for doubles), I think your payment formula is wrong: since the future value of money grows exponentially, the formula should feature raising numbers to a certain power, which it does not.
The correct formula looks as follows (from here):
Since the loan needs to be paid off completely, FV is equal to zero.
Since pow(i+1, n) is used twice, it's a good idea to compute it once, and use the resultant variable in two places. The final version of this computation looks like this:
double calculatePayments(double rate, double loan, int payments) {
double mul = pow(1+rate, payments);
return (loan * mul * rate) / (mul - 1);
}
Demo on ideone computes the payment on $100,000 at 0.004% per month for 30 years at $524.67, which is the same value that excel's PMT function returns.
Note : When you enter the rate of 5.6% in your formula and in another calculator, don't forget that your formula takes the rate per month, not per year. Therefore, the rate that you plug into outside calculators must be 12 times what you enter into your calculator (for 5.6% annually you should enter 0.00466666
One of the first rules of debugging is to make sure you print the inputs to ensure that the program got the values you expected. It didn't, because you wrote:
scanf ("%f", &principal);
Since principal is a double, the format needs to be "%lf". Repeat for the interest rate. You should also check that the inputs succeeded:
if (scanf("%lf", &principal) != 1)
{
fprintf(stderr, "Failed to read principal\n");
return(1);
}
If you'd printed out the input values, you'd have known what was wrong immediately.
Read what dasblinkenlight said.
Also,
Fix your declarations and the variables you are using scanf() for.
principal should be loan. month should be payments.
i is okay. You need to calculate the monthly decimal number of the percentage given.
For instance,
interest = (i/100) /12;
Do that before your function call. Then just basically use dasblinkenlight's function at the bottom of your main.
hope you score a "10" ;)

Resources