Why is my for loop increment changing dramatically? - c

I am writing a small program for amortization using pointers
#include <stdio.h>
#include <string.h>
double power(double a, double b);
int main(void)
{
int loanAmount, number_of_payments, i = 0;
double interestRate, monthlyInterestRate, monthlyPayment;
printf("Enter amount of loan : $ ");
scanf(" %i",&loanAmount);
printf("Enter Interest rate per year : ");
scanf(" %lf",&interestRate);
printf("Enter number of payments : ");
scanf(" %i",&number_of_payments);
monthlyInterestRate = ((interestRate / 100) / 12); //AKA 'r' or rate.
monthlyPayment = (monthlyInterestRate) * (loanAmount/(1 - 1/(power((1 +
monthlyInterestRate), number_of_payments))));
double interest[7] = {0}; //Arbitrarily set to 7 - assuming less payments.
double principal[7] = {0};
double balance[7] = {0};
balance[0] = loanAmount;
double *ipoint,*ppoint,*bpoint,*bpointprev;
ipoint = &interest[0];
ppoint = &principal[0];
bpoint = &balance[0];
bpointprev = bpoint;
printf("Monthly payment should be $ %lf\n",monthlyPayment);
printf("# \t Payment \t Principal \t Interest \t Balance \n");
for (i = 1; i <= number_of_payments; i++) {
ipoint += i;
bpoint += i;
ppoint += i;
*ipoint = *bpointprev * monthlyInterestRate;
*ppoint = monthlyPayment - *ipoint;
*bpoint = *bpointprev - *ppoint;
printf("%i \t %.2f \t %.2f \t\t %.2f \t\t %.2f\n",i,monthlyPayment,*ppoint,*ipoint,*bpoint);
bpointprev += i; //Iterates after logic for next calculation.
}
return 0;
}
double power(double a, double b)
{
double i, sum = 1;
for (i = 0; i < b; i++) {
sum = sum * a;
}
return sum;
}
and came across an issue where the IDE I am writing in runs the program fine:
on Cloud9 IDE:
but on a Unix terminal, the increment variable in my for loop jumps after what seems to be an arbitrary count:
on Unix Terminal:
I am fairly certain it has something to do all of the pointer references I have whizzing around, but I don't know why it would affect the int variable i in the for-loop or why the IDE would handle the error so cleanly. Please educate!

You have a large number of problems with your code that are just waiting to cause problems. As you have discovered, you failed to protect your array bounds by incrementing your pointers with ptr += i causing you to invoke Undefined Behavior by accessing and writing to memory outside of the storage for your arrays.
Take for example interest and ipoint:
double interest[7] = {0};
ipoint = &interest[0];
So your indexes within interest array are as follows and ipoint is initialized to point to the first element in interest:
+---+---+---+---+---+---+---+
interest | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
+---+---+---+---+---+---+---+
^
|
ipoint
Within your loop you are advancing ipoint += i. On the first iteration of your loop, you advance ipoint by one:
+---+---+---+---+---+---+---+
interest | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
+---+---+---+---+---+---+---+
^
|
ipoint
Your second iteration, you advance by two:
+---+---+---+---+---+---+---+
interest | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
+---+---+---+---+---+---+---+
^
|
ipoint
Your third iteration, you advance by three:
+---+---+---+---+---+---+---+
interest | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
+---+---+---+---+---+---+---+
^
|
ipoint
When i = 4 you advance ipoint beyond the end of your array, and you invoke Undefined Behavior when you assign a value to ipoint and attempt to store the value in memory you do no own:
+---+---+---+---+---+---+---+---+---+---+---+
interest | 0 | 1 | 2 | 3 | 4 | 5 | 6 | out of bounds |
+---+---+---+---+---+---+---+---+---+---+---+
^
|
ipoint
Note: when Undefined Behavior is invoked, your code can appear to work normally, or it can SEGFAULT (or anything in between), the operation of your code is simply Undefined and cannot be relied upon from that point forward.
What you need to do is advance each of your pointers by 1, not 'i'. That will insure you do not write beyond your array bounds. You can fix the problem by simply changing 'i' to 1 for each, e.g.
ipoint += 1;
bpoint += 1;
ppoint += 1;
There are a number of other places you risk invoking Undefined Behavior. You fail to check the return of scanf. If you input (by accident, or a cat steps of the keyboard) anything other than a numeric value, a matching failure will occur, no characters will be read from stdin and all further prompts will be skipped and you will then proceed to process with indeterminate value which will invoke Undefined Behavior.
Further, if you enter more than 7 for the number_of_payments or a value less than zero you invoke Undefined Behavior. (the results are also rather uninteresting for number_of_payments = 0) When taking input, not only to you have to validate the conversion succeeds, but you must validate the resulting value is within a usable range -- to avoid Undefined Behavior, e.g.
printf ("Enter number of payments : ");
if (scanf (" %i", &number_of_payments) != 1) {
fprintf (stderr, "error: invalide no. of payments.\n");
return 1;
}
/* validate no. pmts in range */
if (number_of_payments < 1 || number_of_payments > MAXPMTS) {
fprintf (stderr, "error: no. of payments exceed MAXPMTS (%d)\n",
MAXPMTS);
return 1;
}
Lastly, while you are free to initialize ipoint = &interest[0];, it is not necessary. Accessing an array, the array is converted to a pointer to its first element, so ipoint = interest; is all that is required. There are other issues addressed in the comments below, but putting it altogether, you could do something like the following to insure behavior is defined throughout your code:
#include <stdio.h>
#include <string.h>
#define MAXPMTS 32 /* if you need a constant, define one (or more) */
double power (double a, double b);
int main (void)
{
int loanAmount = 0, /* initialize all variables */
number_of_payments = 0,
i = 0;
double interestRate = 0.0,
monthlyInterestRate = 0.0,
monthlyPayment = 0.0;
/* numeric conversions consume leading whitespace (as does %s)
* the ' ' in the conversion doesn't hurt, but isn't required.
*/
printf ("Enter amount of loan : $ ");
if (scanf (" %i", &loanAmount) != 1) { /* validate conversion */
fprintf (stderr, "error: invalid loan amount.\n");
return 1;
}
printf ("Enter Interest rate per year : ");
if (scanf (" %lf", &interestRate) != 1) {
fprintf (stderr, "error: invalid interest rate.\n");
return 1;
}
printf ("Enter number of payments : ");
if (scanf (" %i", &number_of_payments) != 1) {
fprintf (stderr, "error: invalide no. of payments.\n");
return 1;
}
/* validate no. pmts in range */
if (number_of_payments < 1 || number_of_payments > MAXPMTS) {
fprintf (stderr, "error: no. of payments exceed MAXPMTS (%d)\n",
MAXPMTS);
return 1;
}
monthlyInterestRate = ((interestRate / 100) / 12); //AKA 'r' or rate.
monthlyPayment = (monthlyInterestRate) * (loanAmount/(1 - 1/(power((1 +
monthlyInterestRate), number_of_payments))));
double interest[MAXPMTS] = {0};
double principal[MAXPMTS] = {0};
double balance[MAXPMTS] = {0};
balance[0] = loanAmount;
double *ipoint = NULL,
*ppoint = NULL,
*bpoint = NULL,
*bpointprev = NULL;
ipoint = interest;
ppoint = principal;
bpoint = balance;
bpointprev = bpoint;
printf ("Monthly payment should be $ %lf\n", monthlyPayment);
printf ("# \t Payment \t Principal \t Interest \t Balance \n");
/* standard loop is from 0 to i < number_of_payments */
for (i = 0; i < number_of_payments; i++) {
ipoint += 1;
bpoint += 1;
ppoint += 1;
*ipoint = *bpointprev * monthlyInterestRate;
*ppoint = monthlyPayment - *ipoint;
*bpoint = *bpointprev - *ppoint;
/* adjust 'i + 1' for payment no. output */
printf ("%i \t %.2f \t %.2f \t %.2f \t\t %.2f\n",
i + 1, monthlyPayment, *ppoint, *ipoint, *bpoint);
bpointprev += 1; //Iterates after logic for next calculation.
}
return 0;
}
double power(double a, double b)
{
double i, sum = 1;
for (i = 0; i < b; i++) {
sum = sum * a;
}
return sum;
}
(note: whether you loop from i=1 to i <= number_of_payments or from i=0 to i < number_of_payments is largely up to you, but it is standard for the loop variable to track the valid array indexes to protect the bounds of the array. As above, the output for the payment number is simply adjust by i + 1 to produce the desired 1,2,3...)
(also note: in practice you want to avoid using floating-point math for currency. People get really upset when you lose money due to rounding errors. Integer math eliminates that problem)
Look things over and let me know if you have further questions.

This is due to your += i; statements in for-loop , Change it to '++'. When you use += i; , Too much increment is happening for your pointers (not incremented by 1 but by i).
Modified for-loop :-
for (i = 1; i <= number_of_payments; i++)
{
ipoint ++; // not +=i
bpoint ++; // not +=i
ppoint ++; // not +=i
*ipoint = *bpointprev * monthlyInterestRate;
*ppoint = monthlyPayment - *ipoint;
*bpoint = *bpointprev - *ppoint;
printf("%i \t %.2f \t %.2f \t\t %.2f \t\t %.2f\n", i, monthlyPayment, *ppoint, *ipoint, *bpoint);
bpointprev ++; //Iterates after logic for next calculation. not +=i
}
because +=i consumes lot of memory (Too much increment) causing stack smashing error.
Output :-
Enter amount of loan : $ 2000
Enter Interest rate per year : 7.5
Enter number of payments : 6
Monthly payment should be $ 340.662858
# Payment Principal Interest Balance
1 340.66 328.16 12.50 1671.84
2 340.66 330.21 10.45 1341.62
3 340.66 332.28 8.39 1009.35
4 340.66 334.35 6.31 674.99
5 340.66 336.44 4.22 338.55
6 340.66 338.55 2.12 0.00

Related

Pascal Triangle function not working for row 24 & a few others [duplicate]

I'm a computer engineering student and next semester I am going to start C course. So in order to prepare myself a bit, I have started learning C by myself and stumbled across an interesting task, designed for, how it seemed to me at first sight, not a very advanced level.
The task is to write a program to compute the value of a given position in Pascal's Triangle. And the formula given to compute it is written as element = row! / ( position! * (row - position)! )
I've written a simple console program that seems to work okay, until I get to testing it with large numbers.
When trying this program with row 16 and position 3, it calculates the value as 0, although it's obvious that there can't be such a value (in fact it should compute the value as 560), all cells of this triangle are supposed to be integers and be greater than one.
I suppose I'm experiencing a problem with storing and processing large numbers. The factorial function seems to work okay, and the formula I used works until I get to trying large numbers
So far the best solution was found here - How do you printf an unsigned long long int(the format specifier for unsigned long long int)? using inttypes.h library with type uint64_t but it still doesn't give me the result I need.
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
void clear_input(void);
uint64_t factorial(int x);
int main()
{
// Printing
printf("This program computes the value of a given position in Pascal's Triangle.\n");
printf("You will be asked for row and position of the value.\n");
printf("Note that the rows and positions starts from 0.\n");
printf("\n");
printf(" 1 * 0 \n");
printf(" 1 1 * 1 \n");
printf(" 1 2 1 * 2 \n");
printf(" 1 3 3 1 * 3 \n");
printf(" 1 4 6 4 1 * 4 \n");
printf(" **************** \n");
printf(" 0 1 2 3 4 \n");
printf("\n");
// Initializing
int row, pos;
// Input Row
printf("Enter the row: ");
scanf("%d", &row);
clear_input();
// Input Position
printf("Enter the position in the row: ");
scanf("%d", &pos);
clear_input();
// Initializing
uint64_t element, element_1, element_2, element_3, element_4;
// Previously written as -> element = ( factorial(row) ) / ( factorial(pos) * factorial(row - pos) );
// Doesn't fix the problem
element_1 = factorial(row);
element_2 = factorial(pos);
element_3 = factorial(row - pos);
element_4 = element_2 * element_3;
element = element_1 / element_4;
// Print result
printf("\n");
printf("%"PRIu64"\n", element_1); // Temporary output
printf("%"PRIu64"\n", element_2); // Temporary output
printf("%"PRIu64"\n", element_3); // Temporary output
printf("%"PRIu64"\n", element_4); // Temporary output
printf("\n");
printf("The element is %"PRIu64"", element);
printf("\n");
return 0;
}
void clear_input(void) // Temporary function to clean input from the keyboard
{
while(getchar() != '\n');
}
uint64_t factorial(int x) // Function to calculate factorial
{
int f = 1, i = x;
if (x == 0) {
return 1;
}
while (i != 1) {
f = f * i;
i = i - 1;
}
return f;
}
Factorials get really big really fast (scroll down a little to see the list). Even a 64-bit number is only good up to 20!. So you have to do a little preprocessing before you start multiplying.
The general idea is to factor the numerator and the denominator, and remove all of the common factors. Since the results of Pascal's Triangle are always integers, you are guaranteed that the denominator will be 1 after all common factors have been removed.
For example let's say you have row=35 and position=10. Then the calculation is
element = 35! / (10! * 25!)
which is
35 * 34 * 33 * ... * 26 * 25 * 24 * ... * 3 * 2 * 1
---------------------------------------------------
10! * 25 * 24 * ... * 3 * 2 * 1
So the first simplification is that the larger factorial in the denominator cancels all of the smaller terms of the numerator. Which leaves
35 * 34 * 33 * ... * 26
-----------------------
10 * 9 * 8 * ... * 1
Now we need to remove the remaining common factors in the numerator and denominator. It helps to put all the number of the numerator in an array. Then, for each number in the denominator, compute the greatest common divisor (gcd) and divide the numerator and denominator by the gcd.
The following code demonstrates the technique.
array[10] = { 35, 34, 33, 32, 31, 30, 29, 28, 27, 26 };
for ( d = 10; d >= 2; d-- )
{
temp = d;
for ( i = 0; i < 10 && temp > 1; i++ )
{
common = gcd( array[i], temp );
array[i] /= common;
temp /= common;
}
}
Here's what the code does step by step
d=10 i=0 temp=10 array[0]=35 ==> gcd(35,10)=5, so array[0]=35/5=7 and temp=10/5=2
d=10 i=1 temp=2 array[1]=34 ==> gcd(34, 2)=2, so array[1]=34/2=17 and temp=2/2=1
inner loop breaks because temp==1
d=9 i=0 temp=9 array[0]=7 ==> gcd(7,9)=1, so nothing changes
d=9 i=1 temp=9 array[1]=17 ==> gcd(17,9)=1, so nothing changes
d=9 i=2 temp=9 array[2]=33 ==> gcd(33,9)=3, so array[2]=11 and temp=3
d=9 i=3 ==> gcd(32,3)=1
d=9 i=4 ==> gcd(31,3)=1
d=9 i=5 temp=3 array[5]=30 ==> gcd(30,3)=3, so array[5]=10 and temp=1
inner loop breaks
When all is said and done the array ends up as
array[10] = { 1, 17, 11, 1, 31, 1, 29, 14, 3, 26 }
Multiply those numbers together and the answer is 183579396, and the entire calculation could be performed using 32-bit ints. In general, as long as the answer fits into 32-bits, the calculations can be done with 32-bits.
(my C is rusty, so this may not be super accurate)
Your factorial function is returning a uint64_t, but it's doing the computation with regular ints. If you changed f and i to uint64_t I think you'll avoid your current integer overflow issue.
However, you're still going to run into overflow pretty quickly (uint64_t will overflow around 21!). To avoid this you can be a bit smarter with the algorithm. With row=16 and position=3, you need 16! / (3! * 13!). You can cancel out most of the terms (16!/13! is just 14*15*16) and end up with 14*15*16 / (1*2*3). This'll let your program go a lot further than row 21.
When you are calculating the factorial, even though you are returning a 64-bit integer it won't make a difference if you are using regular int variables for your intermediate calculations. Change to this:
uint64_t factorial(uint64_t x)
{
uint64_t f = 1, i = x;
if (x == 0) {
return 1;
}
while (i != 1) {
f = f * i;
i = i - 1;
}
return f;
}
Also, think about how you can rearrange the equation so that you don't have to calculate really large intermediate values. For example you could rearrange to this:
element = ( factorial(row) / factorial(pos) ) / factorial(row - pos);
Then you won't be multiplying two factorials together and getting a really large number.
Also, when you compute factorial(row) / factorial(pos) you can eliminate terms that will be in both factorial(row) and factorial(pos), so you don't need to calculate the entire factorials.
This will work:
#include <stdio.h>
int main()
{
printf ("\n");
int n = 10;
int i;
int j;
int x[n];
for (i = 0; i < n; i++)
x[i] = 0;
for (i = 1; i <= n; i++)
{
for (j = n - 1; j >= 1; j--)
x[j] = x[j-1] + x[j];
x[0] = 1;
int s = n - i;
for (j = 0; j < s; j++)
printf (" ");
for (j = 0; j < n; j++)
{
if (x[j] != 0)
printf (" %3d", x[j]);
}
printf ("\n");
}
printf ("\n");
return 0;
}

Memory Storage for Permutation and Combination functions [duplicate]

I'm a computer engineering student and next semester I am going to start C course. So in order to prepare myself a bit, I have started learning C by myself and stumbled across an interesting task, designed for, how it seemed to me at first sight, not a very advanced level.
The task is to write a program to compute the value of a given position in Pascal's Triangle. And the formula given to compute it is written as element = row! / ( position! * (row - position)! )
I've written a simple console program that seems to work okay, until I get to testing it with large numbers.
When trying this program with row 16 and position 3, it calculates the value as 0, although it's obvious that there can't be such a value (in fact it should compute the value as 560), all cells of this triangle are supposed to be integers and be greater than one.
I suppose I'm experiencing a problem with storing and processing large numbers. The factorial function seems to work okay, and the formula I used works until I get to trying large numbers
So far the best solution was found here - How do you printf an unsigned long long int(the format specifier for unsigned long long int)? using inttypes.h library with type uint64_t but it still doesn't give me the result I need.
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
void clear_input(void);
uint64_t factorial(int x);
int main()
{
// Printing
printf("This program computes the value of a given position in Pascal's Triangle.\n");
printf("You will be asked for row and position of the value.\n");
printf("Note that the rows and positions starts from 0.\n");
printf("\n");
printf(" 1 * 0 \n");
printf(" 1 1 * 1 \n");
printf(" 1 2 1 * 2 \n");
printf(" 1 3 3 1 * 3 \n");
printf(" 1 4 6 4 1 * 4 \n");
printf(" **************** \n");
printf(" 0 1 2 3 4 \n");
printf("\n");
// Initializing
int row, pos;
// Input Row
printf("Enter the row: ");
scanf("%d", &row);
clear_input();
// Input Position
printf("Enter the position in the row: ");
scanf("%d", &pos);
clear_input();
// Initializing
uint64_t element, element_1, element_2, element_3, element_4;
// Previously written as -> element = ( factorial(row) ) / ( factorial(pos) * factorial(row - pos) );
// Doesn't fix the problem
element_1 = factorial(row);
element_2 = factorial(pos);
element_3 = factorial(row - pos);
element_4 = element_2 * element_3;
element = element_1 / element_4;
// Print result
printf("\n");
printf("%"PRIu64"\n", element_1); // Temporary output
printf("%"PRIu64"\n", element_2); // Temporary output
printf("%"PRIu64"\n", element_3); // Temporary output
printf("%"PRIu64"\n", element_4); // Temporary output
printf("\n");
printf("The element is %"PRIu64"", element);
printf("\n");
return 0;
}
void clear_input(void) // Temporary function to clean input from the keyboard
{
while(getchar() != '\n');
}
uint64_t factorial(int x) // Function to calculate factorial
{
int f = 1, i = x;
if (x == 0) {
return 1;
}
while (i != 1) {
f = f * i;
i = i - 1;
}
return f;
}
Factorials get really big really fast (scroll down a little to see the list). Even a 64-bit number is only good up to 20!. So you have to do a little preprocessing before you start multiplying.
The general idea is to factor the numerator and the denominator, and remove all of the common factors. Since the results of Pascal's Triangle are always integers, you are guaranteed that the denominator will be 1 after all common factors have been removed.
For example let's say you have row=35 and position=10. Then the calculation is
element = 35! / (10! * 25!)
which is
35 * 34 * 33 * ... * 26 * 25 * 24 * ... * 3 * 2 * 1
---------------------------------------------------
10! * 25 * 24 * ... * 3 * 2 * 1
So the first simplification is that the larger factorial in the denominator cancels all of the smaller terms of the numerator. Which leaves
35 * 34 * 33 * ... * 26
-----------------------
10 * 9 * 8 * ... * 1
Now we need to remove the remaining common factors in the numerator and denominator. It helps to put all the number of the numerator in an array. Then, for each number in the denominator, compute the greatest common divisor (gcd) and divide the numerator and denominator by the gcd.
The following code demonstrates the technique.
array[10] = { 35, 34, 33, 32, 31, 30, 29, 28, 27, 26 };
for ( d = 10; d >= 2; d-- )
{
temp = d;
for ( i = 0; i < 10 && temp > 1; i++ )
{
common = gcd( array[i], temp );
array[i] /= common;
temp /= common;
}
}
Here's what the code does step by step
d=10 i=0 temp=10 array[0]=35 ==> gcd(35,10)=5, so array[0]=35/5=7 and temp=10/5=2
d=10 i=1 temp=2 array[1]=34 ==> gcd(34, 2)=2, so array[1]=34/2=17 and temp=2/2=1
inner loop breaks because temp==1
d=9 i=0 temp=9 array[0]=7 ==> gcd(7,9)=1, so nothing changes
d=9 i=1 temp=9 array[1]=17 ==> gcd(17,9)=1, so nothing changes
d=9 i=2 temp=9 array[2]=33 ==> gcd(33,9)=3, so array[2]=11 and temp=3
d=9 i=3 ==> gcd(32,3)=1
d=9 i=4 ==> gcd(31,3)=1
d=9 i=5 temp=3 array[5]=30 ==> gcd(30,3)=3, so array[5]=10 and temp=1
inner loop breaks
When all is said and done the array ends up as
array[10] = { 1, 17, 11, 1, 31, 1, 29, 14, 3, 26 }
Multiply those numbers together and the answer is 183579396, and the entire calculation could be performed using 32-bit ints. In general, as long as the answer fits into 32-bits, the calculations can be done with 32-bits.
(my C is rusty, so this may not be super accurate)
Your factorial function is returning a uint64_t, but it's doing the computation with regular ints. If you changed f and i to uint64_t I think you'll avoid your current integer overflow issue.
However, you're still going to run into overflow pretty quickly (uint64_t will overflow around 21!). To avoid this you can be a bit smarter with the algorithm. With row=16 and position=3, you need 16! / (3! * 13!). You can cancel out most of the terms (16!/13! is just 14*15*16) and end up with 14*15*16 / (1*2*3). This'll let your program go a lot further than row 21.
When you are calculating the factorial, even though you are returning a 64-bit integer it won't make a difference if you are using regular int variables for your intermediate calculations. Change to this:
uint64_t factorial(uint64_t x)
{
uint64_t f = 1, i = x;
if (x == 0) {
return 1;
}
while (i != 1) {
f = f * i;
i = i - 1;
}
return f;
}
Also, think about how you can rearrange the equation so that you don't have to calculate really large intermediate values. For example you could rearrange to this:
element = ( factorial(row) / factorial(pos) ) / factorial(row - pos);
Then you won't be multiplying two factorials together and getting a really large number.
Also, when you compute factorial(row) / factorial(pos) you can eliminate terms that will be in both factorial(row) and factorial(pos), so you don't need to calculate the entire factorials.
This will work:
#include <stdio.h>
int main()
{
printf ("\n");
int n = 10;
int i;
int j;
int x[n];
for (i = 0; i < n; i++)
x[i] = 0;
for (i = 1; i <= n; i++)
{
for (j = n - 1; j >= 1; j--)
x[j] = x[j-1] + x[j];
x[0] = 1;
int s = n - i;
for (j = 0; j < s; j++)
printf (" ");
for (j = 0; j < n; j++)
{
if (x[j] != 0)
printf (" %3d", x[j]);
}
printf ("\n");
}
printf ("\n");
return 0;
}

Why my area problem is giving wrong answer?

I am learning c. So, I was practicing in a online judge. I have got a logic behind the problem and submitted ans got wrong answer. What is the problem?
Problem:
Area
100 Points · Limits 1s, 512 MB
In this problem, you will be given a square which has a length of n. Co-ordinates of the square are (0,0), (n,0),(n,n),(0,n) . You need to draw 4 straight lines:
Line from (0,1) to (n,n-1)
Line from (1,0) to (n-1,n)
Line from (0,n-1) to (n,1)
Line from (1,n) to (n-1,0)
These four lines will intersect in a point (x,y) like the figure shown below.
Calculate the total area of A+B+C+D (except the four corner unit square).
Input
Input will start with an integer T. Then there will be T cases. Each case will contain one integer N. 1 <= T <= 100000
3 <= n <= 1018
Output
For each test case, print “Case x: y” without quotation marks where x is the case number and y is the required answer.
It is guaranteed that y is always an integer.
Sample
Input Output
1
6
Case 1: 8
My code:
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
int main()
{
int test, i;
scanf("%d", &test);
for(i=0; i<test; i++)
{
double n, area, a,x, b1, b, s, tri, area1, area_t;
scanf("%lf", &n);
area= n*n;
a=n-2;
x=n/2;
b1= (x-1)*(x-1) + x*x;
b= sqrt(b1);
s= (a+b+b)/2;
area1= s*(s-a)*(s-b)*(s-b);
area_t = (4* sqrt(area1));
printf("Case %d: %.0lf\n",i+1, (area-(area_t + 4)));
}
return 0;
}
Please help me to improve the code. Thank you.
I believe you have a compatability problem and your online judge is on a C89 implementation where "%lf" does not exist, making your program output
Case 1: %.0lf
Case 2: %.0lf
...
Try using the C89 specifier
printf("Case %d: %.0f\n", i + 1, area - (area_t + 4));
/* ^^^^ C89, not %.0lf */
Note: double x; scanf("&lf", &x) has been valid since C89.
Let Area be the requested area, which can be calculated as:
Area = OuterSquareArea - 4 * IsoscelesTringleArea - 4 * SmallSqareArea
where:
OuterSqareArea = n * n
IsoscelesTriangleArea = base * height / 2
= (n - 2) * (n / 2) / 2
= (n - 2) * n / 4
SmallSquareArea = 1 * 1
= 1
The computation of Area can be summed up to:
Area = (n * n) - 4 * ((n - 2) * n / 4) - 4 * (1)
= n * n - (n - 2) * n - 4
= (n - (n - 2)) * n - 4
= 2 * n - 4
The trace guarantees that t, n and Area are integers. The code we need is then:
#include <stdio.h>
int main() {
int i, t, n;
scanf("%d", &t); /* read t */
for (i = 1; i <= t; i++) { /* for any i in [1,t] */
scanf("%d", &n); /* read n */
printf("Case %d: %d\n", i, 2 * n - 4); /* solve */
}
}
The code could simply be extented to check t and n to be in the given ranges.

Pascal's Triangle in C

I'm a computer engineering student and next semester I am going to start C course. So in order to prepare myself a bit, I have started learning C by myself and stumbled across an interesting task, designed for, how it seemed to me at first sight, not a very advanced level.
The task is to write a program to compute the value of a given position in Pascal's Triangle. And the formula given to compute it is written as element = row! / ( position! * (row - position)! )
I've written a simple console program that seems to work okay, until I get to testing it with large numbers.
When trying this program with row 16 and position 3, it calculates the value as 0, although it's obvious that there can't be such a value (in fact it should compute the value as 560), all cells of this triangle are supposed to be integers and be greater than one.
I suppose I'm experiencing a problem with storing and processing large numbers. The factorial function seems to work okay, and the formula I used works until I get to trying large numbers
So far the best solution was found here - How do you printf an unsigned long long int(the format specifier for unsigned long long int)? using inttypes.h library with type uint64_t but it still doesn't give me the result I need.
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
void clear_input(void);
uint64_t factorial(int x);
int main()
{
// Printing
printf("This program computes the value of a given position in Pascal's Triangle.\n");
printf("You will be asked for row and position of the value.\n");
printf("Note that the rows and positions starts from 0.\n");
printf("\n");
printf(" 1 * 0 \n");
printf(" 1 1 * 1 \n");
printf(" 1 2 1 * 2 \n");
printf(" 1 3 3 1 * 3 \n");
printf(" 1 4 6 4 1 * 4 \n");
printf(" **************** \n");
printf(" 0 1 2 3 4 \n");
printf("\n");
// Initializing
int row, pos;
// Input Row
printf("Enter the row: ");
scanf("%d", &row);
clear_input();
// Input Position
printf("Enter the position in the row: ");
scanf("%d", &pos);
clear_input();
// Initializing
uint64_t element, element_1, element_2, element_3, element_4;
// Previously written as -> element = ( factorial(row) ) / ( factorial(pos) * factorial(row - pos) );
// Doesn't fix the problem
element_1 = factorial(row);
element_2 = factorial(pos);
element_3 = factorial(row - pos);
element_4 = element_2 * element_3;
element = element_1 / element_4;
// Print result
printf("\n");
printf("%"PRIu64"\n", element_1); // Temporary output
printf("%"PRIu64"\n", element_2); // Temporary output
printf("%"PRIu64"\n", element_3); // Temporary output
printf("%"PRIu64"\n", element_4); // Temporary output
printf("\n");
printf("The element is %"PRIu64"", element);
printf("\n");
return 0;
}
void clear_input(void) // Temporary function to clean input from the keyboard
{
while(getchar() != '\n');
}
uint64_t factorial(int x) // Function to calculate factorial
{
int f = 1, i = x;
if (x == 0) {
return 1;
}
while (i != 1) {
f = f * i;
i = i - 1;
}
return f;
}
Factorials get really big really fast (scroll down a little to see the list). Even a 64-bit number is only good up to 20!. So you have to do a little preprocessing before you start multiplying.
The general idea is to factor the numerator and the denominator, and remove all of the common factors. Since the results of Pascal's Triangle are always integers, you are guaranteed that the denominator will be 1 after all common factors have been removed.
For example let's say you have row=35 and position=10. Then the calculation is
element = 35! / (10! * 25!)
which is
35 * 34 * 33 * ... * 26 * 25 * 24 * ... * 3 * 2 * 1
---------------------------------------------------
10! * 25 * 24 * ... * 3 * 2 * 1
So the first simplification is that the larger factorial in the denominator cancels all of the smaller terms of the numerator. Which leaves
35 * 34 * 33 * ... * 26
-----------------------
10 * 9 * 8 * ... * 1
Now we need to remove the remaining common factors in the numerator and denominator. It helps to put all the number of the numerator in an array. Then, for each number in the denominator, compute the greatest common divisor (gcd) and divide the numerator and denominator by the gcd.
The following code demonstrates the technique.
array[10] = { 35, 34, 33, 32, 31, 30, 29, 28, 27, 26 };
for ( d = 10; d >= 2; d-- )
{
temp = d;
for ( i = 0; i < 10 && temp > 1; i++ )
{
common = gcd( array[i], temp );
array[i] /= common;
temp /= common;
}
}
Here's what the code does step by step
d=10 i=0 temp=10 array[0]=35 ==> gcd(35,10)=5, so array[0]=35/5=7 and temp=10/5=2
d=10 i=1 temp=2 array[1]=34 ==> gcd(34, 2)=2, so array[1]=34/2=17 and temp=2/2=1
inner loop breaks because temp==1
d=9 i=0 temp=9 array[0]=7 ==> gcd(7,9)=1, so nothing changes
d=9 i=1 temp=9 array[1]=17 ==> gcd(17,9)=1, so nothing changes
d=9 i=2 temp=9 array[2]=33 ==> gcd(33,9)=3, so array[2]=11 and temp=3
d=9 i=3 ==> gcd(32,3)=1
d=9 i=4 ==> gcd(31,3)=1
d=9 i=5 temp=3 array[5]=30 ==> gcd(30,3)=3, so array[5]=10 and temp=1
inner loop breaks
When all is said and done the array ends up as
array[10] = { 1, 17, 11, 1, 31, 1, 29, 14, 3, 26 }
Multiply those numbers together and the answer is 183579396, and the entire calculation could be performed using 32-bit ints. In general, as long as the answer fits into 32-bits, the calculations can be done with 32-bits.
(my C is rusty, so this may not be super accurate)
Your factorial function is returning a uint64_t, but it's doing the computation with regular ints. If you changed f and i to uint64_t I think you'll avoid your current integer overflow issue.
However, you're still going to run into overflow pretty quickly (uint64_t will overflow around 21!). To avoid this you can be a bit smarter with the algorithm. With row=16 and position=3, you need 16! / (3! * 13!). You can cancel out most of the terms (16!/13! is just 14*15*16) and end up with 14*15*16 / (1*2*3). This'll let your program go a lot further than row 21.
When you are calculating the factorial, even though you are returning a 64-bit integer it won't make a difference if you are using regular int variables for your intermediate calculations. Change to this:
uint64_t factorial(uint64_t x)
{
uint64_t f = 1, i = x;
if (x == 0) {
return 1;
}
while (i != 1) {
f = f * i;
i = i - 1;
}
return f;
}
Also, think about how you can rearrange the equation so that you don't have to calculate really large intermediate values. For example you could rearrange to this:
element = ( factorial(row) / factorial(pos) ) / factorial(row - pos);
Then you won't be multiplying two factorials together and getting a really large number.
Also, when you compute factorial(row) / factorial(pos) you can eliminate terms that will be in both factorial(row) and factorial(pos), so you don't need to calculate the entire factorials.
This will work:
#include <stdio.h>
int main()
{
printf ("\n");
int n = 10;
int i;
int j;
int x[n];
for (i = 0; i < n; i++)
x[i] = 0;
for (i = 1; i <= n; i++)
{
for (j = n - 1; j >= 1; j--)
x[j] = x[j-1] + x[j];
x[0] = 1;
int s = n - i;
for (j = 0; j < s; j++)
printf (" ");
for (j = 0; j < n; j++)
{
if (x[j] != 0)
printf (" %3d", x[j]);
}
printf ("\n");
}
printf ("\n");
return 0;
}

Segmentation fault after returning zero

We are being taught programming using C in this semester and in our first assignment we were asked to print the list of values of sin(x), cos(x) and tan(x) using manual and library implementations. So, I wrote the following code:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define START 0
#define STOP 360
#define STEP 10
#define PI 3.14159265358979323846 /*For conversion: degrees <-> radians */
double rad(double x); /* Converts angle in degrees to radians */
double next_term(double angle, int term_index);
/* Function prototypes for manual implementation of sin(x), cos(x) and tan(x) */
double sin_series(double x);
double cos_series(double x);
double tan_series(double x);
int main() {
/* Creating and printing the table title:
** ==================================================================== */
char table_title[] = " n | ";
strcat(table_title, "sin series | sin library | ");
strcat(table_title, "cos series | cos library | ");
strcat(table_title, "tan series | tan library | ");
printf("%s \n", table_title);
/* ==================================================================== */
/* Creating and printing the line between the title and the table:
** ==================================================================== */
char* second_line = (char*)malloc((strlen(table_title) + 1) * sizeof(char));
for (int i = 0; i < strlen(table_title) - 1; i++) {
second_line[i] = '=';
}
second_line[strlen(table_title)] = '\0';
printf("%s \n", second_line);
/* ==================================================================== */
free(second_line);
/* Creating each line of the table and printing it:
** ==================================================================== */
for (int angle = 0; angle < 360; angle += 10) {
printf("%4i | ", angle);
printf("%10.5f | %11.5f | ",sin_series(angle), sin(rad(angle)) );
printf("%10.5f | %11.5f | ",cos_series(angle), cos(rad(angle)) );
printf("%10.5f | %11.5f | ",tan_series(angle), tan(rad(angle)) );
printf("\n");
}
return 0;
}
double rad(double x) {
return ((PI * x) / 180);
}
double next_series_term(double angle, int term_index) {
double result = 1.0;
for (int i = 0; i < term_index; i++) {
result *= angle;
result /= (i + 1);
}
return result;
}
unsigned long long factorial(int x) {
unsigned long long result = 1;
for (int i = 0; i < x; i++) {
result *= (i + 1);
}
return result;
}
double sin_series(double x) {
double result = 0;
if (x == 0 || x == 180 || x == 360) {
result = 0;
}
else {
for (int i = 0; i < 100; i++) {
/* Calculating the next term to add to result to increase precision.*/
double next_term = next_series_term(rad(x), 2*i + 1);
next_term *= pow(-1,i);
result += next_term;
}
}
return result;
}
double cos_series(double x) {
double result = 0;
if (x == 90 || x == 270) {
result = 0;
}
else {
for (int i = 0; i < 100; i++) {
/* Calculating the next term to add to result to increase precision.*/
double next_term = next_series_term(rad(x), 2*i);
next_term *= pow(-1,i);
result += next_term;
}
}
return result;
}
double tan_series(double x) {
return sin_series(x)/cos_series(x); //non-portable! searching for
// better solution
}
But this code results in Segmentation fault after returning 0 as I found after using gdb and has left me completely baffled. Being a novice in C and programming, this has completely baffled me. Please help.
This declaration
char table_title[] = " n | ";
That declares table_title to be an array of eight characters. When you append other strings to the end of the array, you will write out of bounds and have undefined behavior.
Either specify a size big enough to hold all the data you need, or initialize it properly with the complete string.
table_title you assign a string so the sizof(table_title) will not be able to hold the whole string which you are passing so accessing array out of bound is undefined behavior and might cause crash.
Why did you use table_title? There is no need. Just use printf.
printf ("sin series | sin library | cos series | cos library | tan series | tan library | ");
You declared table_title statically. free() is used to deallocate memory that you allocated dynamically. So do it. There wont be segmentation fault.
Ok then you can use printf as
printf (
"sin series | sin library | " \
"cos series | cos library | " \
"tan series | tan library | ");
There is no wraps. Try this. :)

Resources