C Code For loop with nested If; modulus and sqrt issue - c

So, I am trying to get this C code to work. It compiles, but produces incorrect outputs. It should list all pefect square numbers between 1 and a chosen value.
It is doing something wrong, and after alot of trial and error i think the issue is with the modulus operation...like its truncating early or doing some other strange thing.
// C Code
/*This program will identify all square numbers between one and a chosen integer*/
#include <stdio.h>
#include <math.h>
int main(){
int i, upper, square_int;
float square;
printf("This program will identify all square numbers between one and a chosen integer");
printf("Please enter the upper limit integer:");
scanf("%d", &upper);
upper = 13; /*scanf is the primary integer input method; this is here just to test it on codepad*/
for (i = 1; i<= upper; ++i) /*i want to run through all integers between 1 and the value of upper*/
{
square = sqrt(i); /* calc square root for each value of i */
square_int = square; /* change the root from float to int type*/
if (i % (int)square_int == 0) /*check if i divided by root leaves no remainder*/
printf("%d\n", i); /*print 'em*/
}
printf("This completes the list of perfect squares between 1 and %d",upper);
return 0; /*End program*/
}
The output on codepad is:
This program will identify all square numbers between one and a chosen integerPlease enter the upper limit integer:1
2
3
4
6
8
9
12
This completes the list of perfect squares between 1 and 13
Which is of course wrong. I expect to get 1, 2, 4 and 9 back. Can anyone point out my screw up here?

Here is a simpler algorithm
int i = 1;
while (i*i < upper)
{
printf("%d\n", i*i);
++i;
}
Another method is computing the square root, convert it to int, and compare the numbers.
for (i = 1; i <= upper; ++i)
{
square = sqrt(i);
square_int = square;
if (square == (float)square_int)
printf("%d\n", i );
}

Your modulo operation is incorrect. In case of i = 6 square_int will become 2 and thus i % (int)square_int is equal to 6 % 2 which leads to 0.
You could check if square_int * square_int == i instead.

You says you expect to get 1, 2, 4, 9 which means you don't expect to get 3.
Let's see with i == 3:
sqrt(3) == 1.732051
(int) 1.732051 == 1
3 % 1 == 0.
Which means it actually does what it is expected to do but it will not check if a number is a square.
A simple algorithm to check if the number is a square is to do:
sqrt_int = sqrt(i) + 0.5;
if (square_int * square_int == i)
printf("%d\n", i);

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;
}

Armstrong number program in C returns wrong value

I am writing a program to see if a user entered number is Armstrong or not, here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){
int x = 0;
printf("Enter a natural number: ");
scanf("%d", &x);
int ans = x;
// Digit Counter
int counter = 0; //Variable for number of digits in the user entered number
int b = x; //For each time number can be divided by 10 and isnt 0
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b != 0){
counter += 1;
}
}
++counter;
//Digit Counter
int sum = 0;
// Digit Finder
int D;
for (int j = 1; j <= x; j++){
D = x % 10; //Shows remainder of number (last digit) when divided by 10
sum += pow(D, counter); //Raises Digit found by counter and adds to sum
printf("%d\n", sum);
x /= 10; // Divides user entered number by 10 to get rid of digit found
}
if (sum == ans){
printf("%d is a Armstrong number! :)", ans);
}else
printf("%d is not an Armstrong number :(", ans);
//Digit Finder
return 0;
}
My problem is that the program works fine apart from one point, when the program is given a Armstrong number which does not start with 1 then it behaves normally and indicates if it is an Armstrong number or not, but when i input a Armstrong number which start with 1 then it will print out the Armstrong number but -1.
For example: If i input something such as 371 which is an Armstrong number it will show that it is an Armstrong number. However if i input 1634 it will output 1633 which is 1 less than 1634.
How can i fix this problem?, also by the way could someone comment on my code and tell me if it seems good and professional/efficient because i am a beginner in C and would like someone else's opinion on my code.
How can I fix this problem.
You know the number of iterations you want to make once you have calculated the digit count. So instead of looping till you reach the value of x:
for (int j = 1; j <= x; j++){
use the digit counter instead:
for (int j = 1; j <= counter; j++) {
also by the way could someone comment on my code and tell me if it seems good and professional/efficient because i am a beginner in C and would like someone else's opinion on my code.
There's a number of things you can do to improve your code.
First and foremost, any piece of code should be properly indented and formatted. Right now your code has no indenting, which makes it more difficult to read and it just looks ugly in general. So, always indent your code properly. Use an IDE or a good text editor, it will help you.
Be consistent in your code style. If you are writing
if (some_cond) {
...
}
else
//do this
It is not consistent. Wrap the else in braces as well.
Always check the return value of a function you use, especially for scanf. It will save you from many bugs in the future.
if (scanf("%d", &x) == 1)
//...all OK...
else
// ...EOF or conversion failure...
exit(EXIT_FAILURE);
Your first for loop will iterate x times uselessly. You can stop when you know that you have hit 0:
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b == 0){
break;
}
counter += 1;
}
C has ++ operator. Use that instead of doing counter += 1
int D; you create this, but don't initialize it. Always initialize your variables as soon as possible
C has const qualifier keyword, which makes a value immutable. This makes your code more readable, as the reader can immediately tell that this value will not change. In your code, you can change ans variable and make it a const int because it never changes:
const int ans = x;
Use more descriptive names for your variables. ans, D don't tell me anything. Use proper names, so that the reader of your code can easily understand your code.
These are some of the things that in my opinion you should do and keep doing to improve your code and coding skills. I am sure there can be more things though. Keep your code readable and as simple as possible.
The condition in this loop
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b != 0){
counter += 1;
}
}
does not make sense because there will be numerous redundant iterations of the loop.
For example if x is equal to 153 that is contains only 3 digits the loop will iterate exactly 153 times.
Also additional increment of the variable counter after the loop
++counter;
makes the code logically inconsistent.
Instead of the loop you could write at least the following way
int counter = 0;
int b = x;
do
{
++counter;
} while ( b /= 10 );
This loop iterates exactly the number of times equal to the number of digits in a given number.
In this loop
for (int j = 1; j <= x; j++){
D = x % 10; //Shows remainder of number (last digit) when divided by 10
sum += pow(D, counter); //Raises Digit found by counter and adds to sum
printf("%d\n", sum);
x /= 10; // Divides user entered number by 10 to get rid of digit found
}
it seems you did not take into account that the variable x is decreased inside the body of the loop
x /= 10; // Divides user entered number by 10 to get rid of digit found
So the loop can interrupt its iterations too early. In any case the condition of the loop again does not make great sense the same way as the condition of the first loop and only adds a bug.
The type of used variables that store a given number should be unsigned integer type. Otherwise the user can enter a negative number.
You could write a separate function that checks whether a given number is an Armstrong number.
Here you are.
#include <stdio.h>
int is_armstrong( unsigned int x )
{
const unsigned int Base = 10;
size_t n = 0;
unsigned int tmp = x;
do
{
++n;
} while ( tmp /= Base );
unsigned int sum = 0;
tmp = x;
do
{
unsigned int digit = tmp % Base;
unsigned int power = digit;
for ( size_t i = 1; i < n; i++ ) power *= digit;
sum += power;
} while ( ( tmp /= Base ) != 0 && !( x < sum ) );
return tmp == 0 && x == sum;
}
int main(void)
{
unsigned int a[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407,
1634, 8208, 9474, 54748, 92727, 93084, 548834
};
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
printf( "%u is %san Armstrong number.\n", a[i], is_armstrong( a[i] ) ? "": "not " );
}
return 0;
}
The program output is
0 is an Armstrong number.
1 is an Armstrong number.
2 is an Armstrong number.
3 is an Armstrong number.
4 is an Armstrong number.
5 is an Armstrong number.
6 is an Armstrong number.
7 is an Armstrong number.
8 is an Armstrong number.
9 is an Armstrong number.
153 is an Armstrong number.
370 is an Armstrong number.
371 is an Armstrong number.
407 is an Armstrong number.
1634 is an Armstrong number.
8208 is an Armstrong number.
9474 is an Armstrong number.
54748 is an Armstrong number.
92727 is an Armstrong number.
93084 is an Armstrong number.
548834 is an Armstrong number.
Please remove j++ from 2nd loop for (int j = 1; j <= x; j++)
I tried this:
void armstrong(int x)
{
// count digits
int counter = 0, temp = x, sum = 0;
while(temp != 0)
{
temp = temp/10;
++counter; // Note: pre increment faster
}
// printf("count %d\n",counter);
temp = x;
while(temp != 0)
{
sum += pow(temp % 10, counter);
temp = temp/10;
}
// printf("sum %d\n",sum);
if(x == sum)
{
printf("Armstrong\n");
}
else
{
printf("No Armstrong\n");
}
}
int main(){
armstrong(371);
armstrong(1634);
return 0;
}
Let's take this and add the ability to handle multiple numeric bases while we're at it. Why? BECAUSE WE CAN!!!! :-)
#include <stdio.h>
#include <math.h>
double log_base(int b, double n)
{
return log(n) / log((double)b);
}
int is_armstrong_number(int b, /* base */
int n)
{
int num_digits = trunc(log_base(b, (double)n)) + 1;
int sum = 0;
int remainder = n;
while(remainder > 0)
{
sum = sum + pow(remainder % b, num_digits);
remainder = (int) (remainder / b);
}
return sum == n;
}
int main()
{
printf("All the following are valid Armstrong numbers\n");
printf(" 407 base 10 - result = %d\n", is_armstrong_number(10, 407));
printf(" 0xEA1 base 16 - result = %d\n", is_armstrong_number(16, 0xEA1));
printf(" 371 base 10 - result = %d\n", is_armstrong_number(10, 371));
printf(" 1634 base 10 - result = %d\n", is_armstrong_number(10, 1634));
printf(" 0463 base 8 - result = %d\n", is_armstrong_number(8, 0463));
printf("All the following are NOT valid Armstrong numbers\n");
printf(" 123 base 10 - result = %d\n", is_armstrong_number(10, 123));
printf(" 0x2446 base 16 - result = %d\n", is_armstrong_number(16, 0x2446));
printf(" 022222 base 8 - result = %d\n", is_armstrong_number(8, 022222));
}
At the start of is_armstrong_number we compute the number of digits directly instead of looping through the number. We then loop through the digits of n in base b, summing up the value of the digit raised to the number of digits in the number, for the given numeric base. Once the remainder hits zero we know there are no more digits to compute and we return a flag indicating if the given number is an Armstrong number in the given base.

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;
}

Sum of Digits using recursion in C

For our activity today, we were tasked to make using recursion with the sum of digits. I already made this program:
int main()
{
int num = 0, sum;
printf("Enter an integer: ");
scanf("%d",&num);
//counter=1;
for ( sum=0; num>0;)
{
sum = sum + num % 10;
num = num /10;
}
printf("Sum = %d", sum);
getch();
return 0;
}
Our teacher added "Input and output must be done in the main() function." Am doing the right thing? Or am I missing something in my code?
To do recursion, create a function that recurses rather than using a for loop.
int SumDigits(int i) {
if (i < 10) {
return i;
}
else {
return i%10 + SumDigits(i/10);
}
}
scanf("%d", &i);
printf("%d\n", SumDigits(i));
What you have there is an iterative solution, not a recursive one.
Recursion involves defining the problems in terms of a simpler version of the problem, all the time working towards a fixed end point.
The fixed end point in this case is any number less than 10, for which the value is that digit.
The transition to a simpler case (for numbers greater than 9) is simply to add the least significant digit to the result of the number divided by ten (integer division).
Since it's classwork, pseudo-code only I'm afraid.
def digitSum (n):
if n < 10:
return n
return (n % 10) + digitSum (n / 10)
If you follow that for the number 314, you'll see what happens.
At recursion level one, n == 314 so it calculates 314 % 10 to get 4 and calls digitSum(31).
At recursion level two, n == 31 so it calculates 31 % 10 to get 1 and calls digitSum(3).
At recursion level three, n == 3 so it just returns 3
Back up to level two, that's added to the remembered 1 and returned as 4.
Back up to level one, that's added to the remembered 4 and returned as 8.
Hence you end up with the digit sum of 8 for the number 314.

Resources