Gauss distribution using rand() - c

i am up to build a Monte Carlo based simulation in C since it is super fast and I was wondering why my code is producing a even distribution.
So first to pick you up, bevor I started coding I imagened the picture of a few balls falling down and on every dot they can move left or right with random distribution. The picture is showen here: https://www.youtube.com/watch?v=PM7z_03o_kk.
But what I got is kind of strange. When I set the scatterpoints to 10 (which is in the code example setted to 100):
while(j < 100) // Number of abitrary change of direction
I got a picture like a Gauss-Distribution but only even bin´s are contributing to it. When its large enough like shown in the code, every bin got about the same amount of particles. This is the 2D case which will be expanded to the 3D case once it is working as expected.
There are still some Variables in it which are not really neccessary just to avoid any possible mistake I can imagine. I was working with gdb to find the error. When I just run distr() with gdb I figured out that it is producing only even numbers if the example above is setted to 10. When I go to 11 I found out, that bin[0] starts to contribute with a very small amout compared to the rest. I also ran rando() enough times to see if it's really pseudo-random and I found out that it should work.
I was still not able to figure out the mistake, so I really hope that here are enough people smarter than me oO.
Full code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define SEED time(NULL)
int rando(void) // Monte Carlo method for choosing weather left or right
{
double temp=0;
temp = (double) rand()/RAND_MAX; // pseudo random number between 0-1
if (temp >= 0.5)
return 1; // Particle to the right
if (temp < 0.5)
return 0; // Particle ot the left
else
return EXIT_FAILURE;
}
int distr(void) // Binning particle
{
int i=10; // Center of bin
int j=0;
int k=0;
while(j < 100) // Number of abitrary change of direction
{
k=rando();
if(k == 1)
{
if ( i < 13) // Choose upper bound of bins
i++;
j++;
}
if(k == 0)
{
if (i > 7) // Choose lower bound of bins
i--;
j++;
}
}
return i;
}
int main(void)
{
srand ( SEED );
int* bin;
int binning;
int k=0;
int l=0;
int iter;
fprintf(stdout, "\nIterations: ");
fscanf(stdin, "%d", &iter);
bin = malloc(21*sizeof(int));
while (k < 20)
{
bin[k] = 0;
k++;
}
k = 0;
while(k < iter) // Count of particle ot distribute
{
binning = distr(); // Choosing the bin
bin[binning]+=1; // Counting binned particle per bin
k++;
}
while(l < 20)
{
fprintf(stdout, "\n %d", bin[l]);
l++;
}
return EXIT_SUCCESS;
}
I can't wait to read you and thanks in advance,
Maleware

Among several other issues, there are a couple of logical errors in the implementation of the distr function and its caller.
In the linked video, the "obstacles" are shaped in lines forming a triangle:
. Falling balls.
.
. *
. * . *
. * * . * Obstacles.
. * * . * *
. * * . * * *
. .
. | | o | | | Allowed result.
. |___|___|___|___|
.
o Rejected.
Note that the obstacles are spread in staggered lines, every bin can be "fed" by two obstacle, and that some balls will end up outside the allowed bins.
The posted code seems to implement another model:
.
-1 . +1
<--.-->
.[*]. If the choice is between +1 and -1...
. .
. .
. .
.[*]. [X] [*]. One out of two obstacles can't be reached.
. . .
. . .
. . .
[*]. [x] .[*] [X] [*].
. . .
. .
. .
. .
| | X | o | X | | X | . | The same happens to the bins.
| | | . | | | | o |
| | | o | | | | |
|_____|_____|_____|_____|_____|_____|_____|
There are no rejections, only unreachable bins, the odd ones or the even ones depending on the number of lines of obstacles.
If there are enough lines of obstacles, more than the number of bins, the "balls" can't escape outside and they fall into the corresponding obstacle in the successive line (effectively a 0 movement). Now they start spreading towards the center, filling all the bins, in what is definetely not a normal distribution.
I'd suggest to consider a different random walk, one that advance or not by one:
|
[1] .\.
[0] . | .
[0] . | .
[1] . \ .
[0] . | .
[1] . \ .
[1] . \ .
[0] . | .
v
| | | | | | | | | |
0 1 2 3 4 5 6 7 8
^ Result
Which could be implemented as easily as this unoptimized function
int random_walk(int steps)
{
int count = 0;
while ( steps-- )
{
count += rand() > RAND_MAX / 2;
}
return count;
}
Note, though, that it uses only one bit of the value returned by rand and that the final result is the total number of non-zero bits. I leave all the possible optimization to the reader.

Apparently with the same even number of +1 or -1's you will always get an even number for the final bin. so if you start as you did with an odd bin starting point the final bin will be odd. Start with an even bin # as I did you will get an even final bin. So what I did was randomly start with j = 1 or 0 so you get about half odd number of movements and half even. I reduced the number of iterations to 50 and increased the number of bins so that most of the results (99%) are captured. You now get a nice normal distribution.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define SEED time(NULL)
int rando(void) // Monte Carlo method for choosing weather left or right
{
return rand() & 1;
}
int distr(void) // Binning particle
{
int i=20; // Center of bin
int j=rand() & 1; // makes the number if movements either odd or even
int k=0;
while(j < 50) // Number of 50 or 49 changes of direction
{
k=rando();
if(k == 1)
{
i++;
j++;
printf(" i = %d ", i);
}
if(k == 0)
{
i--;
j++;
printf(" i = %d ", i);
}
}
return i;
}
int main(void)
{
srand ( SEED );
int* bin;
int binning;
int k=0;
int iter;
printf("\nIterations: ");
scanf("%d", &iter);
bin = malloc(21*sizeof(int));
while (k < 40) // zero's out bin[0] to bin[39]?
{
bin[k] = 0;
k++;
}
k = 0;
while(k < iter) // Count of particle of distribute
{
binning = distr(); // Choosing the bin
printf("binning = %d ", binning);
bin[binning]+=1; // Counting binned particle per bin
k++;
}
int l = 0;
while(l < 40)
{
printf("\n %d", bin[l]);
l++;
}
/* total the mumber of iterations of distr() */
int total = 0;
l = 0;
while(l < 40)
{
total += bin[l];
l++;
}
printf("\n total number is %d\n\n", total);
return 0;
}

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

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. :)

Big integers using array in C

#include <stdio.h>
#include <math.h>
int main(void) {
int a[100], carry,i,j=0,length=0,temp,leftcarry=0,l,n;
clrscr();
scanf("%d",&n);
for(i=0;i<100;i++) a[i]=0;
for(i=1;i<=n;i++){
a[j]+=i;
while(a[j]>=10){
carry=a[j]%10;
if(a[j]>=pow(10,(j+1))){
if(leftcarry==0){
a[j]=a[j]/10;
j++;
a[j]+=carry;
if(j>length)length=j;
}
else{
for(l=j+1;l<=length;l++){
temp=a[l+1];
a[l+1]=a[l];
a[l+2]=temp;
}
a[j+1]=carry;
leftcarry=0;
length=length+1;
}
}
else{
a[j]=a[j]/10;
a[j-1]+=a[j];
a[j]=carry;
j--;
if(a[j]>=10) leftcarry=1;
}
}
j=length;
}
for(i=0;i<=length;i++){
printf("%d",a[i]);
}
return 0;
}
I wanted to get some experience handling big integers using arrays, so I wrote this code to find sum of first n natural numbers. I got the right answer for given number<45. But for given number>=45, I get the answer which is less than the correct answer by 2. I would like to know why it is so. And I would also like to know of other simpler methods of handling big integers. Thank you.
Edit: Thank you all for answering. The question is now solved.
I think this line is an error:
if(a[j]>=pow(10,(j+1))){
I don't know if it's the error or the only error.
This says 'If the j-placed digit is greater than or equal to 10^(j+1)'.
I think the carry test is just 'is the j-place digit greater than or equal to 10.
The 'order' of that digit is identified by it's place. It's sometimes called place value notation!
It's as though the 'digit' in the 'tens' column can go up to 99 and the 'digit' in the thousands column can go up to 999. I don't think that's what you want.
{999,99,9} isn't a decimal number! That ought to be {9,9,9,9,9,9}.
As others have also suggested I very strongly suggest you implement a little-endian scheme where the least significant digit is at the start of the array.
Then it becomes a whole load easier because you don't need all that shuffling down code to make space.
Then the algorithm as you've implemented becomes:
Add i to the units (which are housed at a[0]).
If a[0]>9, overflow! Take the 'excess' and iteratively move up the number (up the array) adding the excess (divided by 10) looking for further overflow at each step.
You should keep track of the 'order' of the number (largest i for which a[i]!=0) to detect overflow of the fixed-length array.
Your next challenge is to write a function int add_small(int a[100],int d,int p){}.
That adds the number d*10^p to a where 0<=d<=10 and 0
After that int add_big(int a[100],int b[100]) calling add_small in a loop.
In case it helps your Googling (and you don't already know) what you're doing here is called 'binary coded decimal'. It's a very natural way to translate base 10 into a computer program but not (in fact) a very efficient way to handle big integer.
It's considered a bit hardcore but you should refer to The Art of Computer Programming Vol. 1 Chapter 4.3.1 'The Classical Algorithms'. If you're not a computer science undergraduate you're allowed to give that a miss. If you are a computer science undergraduate you're obliged to go to the library immediately and read it.
EDIT: I just looked at your profile. "CSE Undergraduate Student, First Year". Library it is.
EDIT: Hints if you insist on your heretical big-endian implementation!
Set j=length-1
Set a[j]+=i (the addition)
If a[j]>=10 divide it by 10 and take the remainder.
Set the remainder in a[j]
If j is zero, go to Full Overflow!
Otherwise, reduce j and add the division result in step 3 to a[j] and go back to step 3 again.
Finished!
Full Overflow: If j reached zero, shuffle everything up a slot, increment length and put the underflow division from step 3 in to a[0] like step 3.
Given your implementation you might full underflow multiple times so that needs to be a loop.
I would say that there's a structural error in your program more common for novices than experienced programmers. You're just trying to do too much in one loop.
Divide and conquer! That's how we solve computing problems.
Divide you function into an ordinary addition loop and then this shuffling loop that lays the overflowing digits out at the end of the number.
As I keep pointing out it would be simpler if you were little-endian!
This is the code I wrote to reimplement the solution, using the 'litle-endian' approach with a[0] containing the units digit, a[1] containing the tens digit, etc.
#include <stdio.h>
int main(void)
{
int a[100];
int length = 0;
int n;
if (scanf("%d", &n) != 1 || n < 0)
return 1;
for (int i = 0; i < 100; i++)
a[i] = 0;
for (int i = 1; i <= n; i++)
{
int carry = 0;
int number = i;
int j;
for (j = 0; carry > 0 || number > 0; j++)
{
int digit = number % 10;
number /= 10;
a[j] += digit + carry;
carry = 0;
if (a[j] >= 10)
{
a[j] -= 10;
carry = 1;
}
}
if (j > length)
length = j;
}
printf("%d ", n);
for (int i = length; i > 0; i--)
printf("%d", a[i-1]);
long l = n;
printf(" %ld\n", (l * (l + 1)) / 2);
return 0;
}
Its output is the input value, the series of digits printed from the 'big number' array, and the result of the formula as a direct calculation (since ∑x = n·(n+1)÷2, for x in 1..n). I tested it with variations on this script:
$ for i in $(range 40 50); do bn <<< $i; done
'bn' is up to date.
40 820 820
41 861 861
42 903 903
43 946 946
44 990 990
45 1035 1035
46 1081 1081
47 1128 1128
48 1176 1176
49 1225 1225
50 1275 1275
$
And then more comprehensively with variations on this script:
$ for i in $(random -n 10 100000 999999 | sort -n)
> do
> bn <<< $i
> done |
> awk '{ print; if ($2 != $3) print "BUG: " $1 " -- " $2 " != " $3 }'
291478 42479857981 42479857981
393029 77236093935 77236093935
396871 78753493756 78753493756
490344 120218864340 120218864340
577519 166764386440 166764386440
580196 168313989306 168313989306
640090 204857924095 204857924095
876878 384457951881 384457951881
892825 398568686725 398568686725
974712 475032228828 475032228828
$
I actually used a repeat of 1000 instead of just 10, and the ranges moved up 10,000..99,999 and then 100,000..999,999; prior to that, I'd done similar proving with lower ranges and sequential numbers.
And I extended the tested range upwards:
$ for i in $(random -n 10 1000000 9999999 | sort -n); do bn <<< $i; done | awk '{ print; if ($2 != $3) print "BUG: " $1 " -- " $2 " != " $3 }'
1291994 834624894015 834624894015
2032157 2064832052403 2064832052403
2266405 2568296945215 2568296945215
3187934 5081463188145 5081463188145
6045841 18276099721561 18276099721561
7248630 26271322062765 26271322062765
8604056 37014894127596 37014894127596
9095266 41361936353011 41361936353011
9533328 45442176144456 45442176144456
9543073 45535125913201 45535125913201
$ for i in $(random -n 10 10000000 99999999 | sort -n); do bn <<< $i; done | awk '{ print; if ($2 != $3) print "BUG: " $1 " -- " $2 " != " $3 }'
11451834 65572256707695 65572256707695
44931846 1009435414949781 1009435414949781
55847914 1559494776999655 1559494776999655
72229304 2608536214276860 2608536214276860
81242212 3300148545947578 3300148545947578
88702606 3934076199946921 3934076199946921
89386055 3994933458924540 3994933458924540
93246667 4347470499927778 4347470499927778
95651750 4574628686857125 4574628686857125
97417038 4745039695055241 4745039695055241
$
(And yes, while I was testing early versions of the code, I did get some broken outputs.)
Simple implementation.
(this small one cell is to ensure that the carry happen.)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
//range of one cell represent : 00-99
#define Base 100
#define Width 2
#define PRN PRIu8
typedef struct _unums {
size_t size;
uint8_t *nums;
} UNums;
void UNums_init(UNums *num){
num->nums = malloc(sizeof(*num->nums));
num->nums[0] = 0;
num->size = 1;
}
void UNums_print(UNums *num){
size_t i = num->size;
int w = 0;
do{
--i;
printf("%0*" PRN, w, num->nums[i]);
if(!w) w = Width;
}while(i!=0);
}
void UNum_drop(UNums *num){
free(num->nums);
num->nums = NULL;
}
//num += n. (n + num->nums[0] <= UINT_MAX) to work properly.
void UNums_add1(UNums *num, unsigned n){
unsigned carry = n, wk;
size_t i;
for(i=0;i<num->size;++i){
wk = num->nums[i] + carry;
num->nums[i] = wk % Base;
carry = wk / Base;
}
while(carry){
num->size += 1;
num->nums = realloc(num->nums, num->size * sizeof(*num->nums));
num->nums[i++] = carry % Base;
carry /= Base;
}
}
int main(void){
UNums num;
unsigned i, n;
UNums_init(&num);
scanf("%u", &n);
for(i=1;i<=n;++i)
UNums_add1(&num, i);
UNums_print(&num);
UNum_drop(&num);
return 0;
}

Resources