Calculation of factorial of large numbers in c using arrays - c

I am trying to calculate factorial of very large numbers in c like 100!..by dynamically allocating memory after calculating the number of digits in factorial:
My code is:
int main()
{
int n,q,i,j,z,t,d;
float p=0.0;
printf("Enter the number whose factorial is to be calculated:\n");
scanf("%d",&n);
//calculating number of digits
for(j=2;j<=n;j++)
p=p+log10(j);
d=(int)p+1;
printf("No of digits in the factorial are:%d\n",d);
int *a;
a=(int *)malloc(d*sizeof(int));//allocation of memory
a[0]=1;
for(i=1;i<n;i++)//initialize array
a[i]=0;
p=0.0;
for(j=2;j<=n;j++)
{
q=0;
p=p+log10(j);
z=(int)p+1;
for(i=0;i<z;i++)
{
t=(a[i]*j)+q;
q=t/10;
a[i]=t%10;
}
}
printf("\n");
for(i=d-1;i>=0;i--)
{
printf("%d",a[i]);
}
return 0;
}
Its providing correct answers upto 40! but not after that!What is wrong with my solution?

The problem is probably because of this loop:
for(i=1;i<n;i++)//initialize array
In the loop you clear the n - 1 entries of the allocated memory, but you allocate memory for d entries. If n - 1 is larger than d then you write outside the allocated memory, which causes undefined behavior. If n - 1 is smaller than d then you leave some memory uninitialized which also is undefined behavior when you access it.
You should clear all of the memory, either by using your loop, by using memset or by using calloc when allocating.

may be you can use memset in case not quite interested in calloc, also I guess null check is mandatory
so instead of this looping
a=(int *)malloc(d*sizeof(int));//allocation of memory
a[0]=1;
for(i=1;i<n;i++)//initialize array
a[i]=0;
a simple call
a=(int *)malloc(d*sizeof(int));//allocation of memory
if(a == NULL)
{
printf("OOM Error");
exit(1);
}
memset(a, 0 , d*sizeof(int));

int main()
{
int i,j,n,m=0;
scanf("%d",&n);
int arr[2000];
int temp=0;
int inter=1;
arr[0]=1;
for(i=1;i<n;i++)
{
for(j=0;j<=m;j++)
{
inter=arr[j]*i+temp;
arr[j]=inter%10;
temp=inter/10;
if( temp>0 && j==m )
m++;
}
}
for(i=m;i>=0;i++)
{
printf("%d",arr[i]);
}
return 0;
}

Related

This code in C which decides if a number is a prime number crashes with large numbers. Why?

So this is the code and it works perfectly fine till 4-5 digits.
int main()
{
int x;
printf("Enter a number: ");
scanf("%d", &x);
double list[x];
int i;
for(i=0;i<x;i++){
list[ i ] = i+1;
}
double z;
int q;
double list2[x];
for(q=0;q<x;q++){
z=x/list[q];
if (z == floor(z)){
list2[q] = z;
}
else {
list2[q] = 0;
}
}
printf("\n--------------\n");
int n;
double nulla = 0.00000000;
int zero = 0;
for(n = 0; n < x; n++)
{
if (fabs(list2[n]-0.00)==0.00){
zero++;
}
}
if(zero == x-2){
printf("It is a prime number");
}
else{
printf("It is not a prime number");
}
printf("\n--------------\n");
return 0;
}
But if i input for example 987521. It just gives this message: Process returned -1073741571 (0xC00000FD) and I have been thinking that maybe an array cannot store such a large data, but maybe i am wrong. Any thoughts?
Instead of allocating memory on the stack, as you do in the line
double list[x];
use dynamic allocation, like
double* list = malloc(x * sizeof(double));
Then, before the end of the program, don't forget to deallocate:
free(list);
The reason is that stack allocation is usually quite limited in size (order of MBs), and you'll overflow the stack once you allocate more than that limit. On the other had, dynamic memory (heap) is limited by the operating system, and can usually be quite large (limited by either the OS or the amount of total physical + virtual memory).

Why for loop terminates after running only 4 times?

I want that array (marks) size increases by 1 with each input of user:
#include <stdio.h>
main() {
int size=1;
int marks[size];
int i;
printf("Enter marks\n");
for(i=0;i<size;i++) {
scanf("%d",&marks[i]);
size++;
}
}
You can't increase the size of your array dynamically. But if you know how many scores will be entered, then you can set size to that value and then accept values until that size is reached.
#include <stdio.h>
int main()
{
int size = 10;
int marks[size];
int i;
printf("Enter marks\n");
for(i = 0; i < size; i++)
{
scanf("%d",&marks[i]);
}
}
Resizing dynamically will increase the complexity of your program significantly, but if that's exactly what you're trying to do, check out R Sahu's answer here or this answer: increasing array size dynamically in c.
Because you have statically declared marks array to size 1. Since you are incrementing size in loop will lead to undefined behavior. Better approach would be allocate marks dynamically.
Consider below example for reference.
#include <stdio.h>
#include<stdlib.h>
void main() {
int size=0;
int *marks = NULL;
int i;
printf("Enter number of marks\n");
scanf ("%d",&size);
marks = (int *) malloc(size*sizeof(int));
printf("Enter marks\n");
for(i=0;i<size;i++)
{
scanf("%d",&marks[i]);
}
}
Your code assumes an increase in size will increase the size of the native array. That isn't how arrays work in C.
Native arrays in C are fixed-length after their definition. If you want to dynamically grow a sequence of things, then you need to manage a dynamic sequence, doing it inner-loop as valid data is received.
Code
The following prompts (or lack thereof) the user in the same fashion your code apparently desired. However, a loop termination condition has been added (a mark entry of -1 will terminate the loop, as will any invalid non-convertible input).
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *marks = NULL, mark = 0;
int size = 0;
printf("Enter marks\n");
while (scanf("%d", &mark) == 1 && mark != -1)
{
// expand marks
void *tmp = realloc(marks, (size+1) * sizeof *marks);
if (tmp == NULL)
{
perror("Failed to expand marks array");
exit(EXIT_FAILURE);
}
marks = tmp;
marks[size++] = mark;
}
// TODO: use marks[0] through marks[size-1] here
for (int i=0; i<size; ++i)
printf("%d ", marks[i]);
fputc('\n', stdout);
// then free marks
free(marks);
return EXIT_SUCCESS;
}
Sample Input
1 2 3 4
5 6
7 8 9
10 -1
Output
1 2 3 4 5 6 7 8 9 10
Notes: There are more efficient geometric growth algorithms that considerably reduce the number of realloc calls, For example, doubling the prior sequence size with each realloc and tracking both size and capacity would reduce your number of allocations from n to log(n). However, for the basic understanding of inline sequence growth, this example should suffice.
I want that array (marks) size increases by 1 with each input of user.
That's not how arrays work in C.
To get that functionality, you'll have to use dynamically allocated memory using malloc and realloc.
Also, your code has a logic flaw. If you look at the variables that control the loop, you have:
int size=1;
int i;
for(i=0;i<size;i++) { // i will never catch up to size before size overflows
size++;
}
For your needs, you can use a variable length array (VLA) or use malloc only once.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int size;
int i;
printf("Enter size\n");
if ( scanf("%d", &size) != 1 )
{
// Problem. Deal with error.
}
// Use a VLA
int marks[size];
// or
// Allocate memory.
// int* marks = malloc(sizeof(*marks)*size);
printf("Enter marks\n");
for ( i = 0; i < size; i++)
{
if ( scanf("%d", &marks[i]) != 1)
{
// Problem. Deal with error.
}
}
// Deallocate the memory. Needed when using malloc
// free(marks);
}
#include <stdio.h>
#include <stdlib.h>
main() {
int size=1;
int *marks = NULL;
int i;
printf("Enter marks\n");
for(i=0;i<size;i++)
{
int *tmpptr = realloc(marks, size * sizeof(*mark));
if(!tmpptr)
{
printf("Memeory allocation error\n");
free(marks);
break;
}
marks = tmpptr;
if(scanf("%d",marks + i) != 1) break;
size++;
}
/* some code */
}

CodeChef runtime error(sigsegv)

CodeChef Problem:
Shivam is the youngest programmer in the world, he is just 12 years old. Shivam is learning programming and today he is writing his first program.
Program is very simple, Given two integers A and B, write a program to add these two numbers.
Input
The first line contains an integer T, total number of test cases. Then follow T lines, each line contains two Integers A and B.
Output
Add A and B and display it.
Constraints
1 ≤ T ≤ 1000
1 ≤ A,B ≤ 10000
Example
Input
3
1 2
100 200
10 40
Output
3
300
50
#include <stdio.h>
int main()
{
int T, A, B, i, sum[T];
scanf("%d", &T);
for(i=0;i<T;i++)
{
scanf("%d",&A);
scanf("%d",&B);
sum[i]=A+B;
}
for(i=0;i<T;i++)
{
printf("\n%d", sum[i]);
}
}
Error
Runtime Error SIGSEGV - I searched it, it says array out of bounds.
T has an indeterminate value when you declare sum[T]. Instead, do:
int main()
{
int T, A, B, i;
scanf("%d", &T);
int sum[T];
for(i=0;i<T;i++) ...
Ans you should check the return value of scanf.
If you want to allocate the memory runtime (during the programs execution) it would be more appropriate to use a function such as "malloc". Here is a short example.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int T, A, B, i;
int *sum;
scanf("%d", &T);
if (T <= 0) /*Check if the value of T is appropriate*/
{
fprintf(stderr, "Invalid argument T!\n");
}
/* Dynamically allocate the memory */
sum = (int *)malloc(sizeof(int)*T);
if (sum == NULL)
{
fprintf(stderr, "Failed to allocate memory!\n");
}
for(i=0;i<T;i++)
{
scanf("%d",&A);
scanf("%d",&B);
sum[i]=A+B;
}
for(i=0;i<T;i++)
{
printf("\n%d", sum[i]);
}
/* Free the allocated memory once you are not needing it anymore in
order to avoid memory leaks */
free(sum);
return (0);
}
Note: This is just an example how to avoid the runtime error I have not taken a close look at the rest of the logic related with the for loops.
Declare sum[T] after taking the input value of T

Code blocks, adding and storing integers through a function

So I'm trying to get a simple program to work by asking the user to enter numbers within 1-100 and have the program store everything entered then tell the user later on all the numbers and how much it adds up to be.
Right now all I want to know is how do I store the variables and have the program be able to tell me how many numbers were entered.
Should I make a function outside of main that does the processing for storing and adding?
#include <stdio.h>
int main () {
int number, even, odd;
char name;
printf("Enter your name")
scanf(%d, &number);
scanf (%c, &char)
printf("Enter numbers within 1-100")
printf("Enter 0 to quit")
while (number != 0) {
if (number%2 == 1) {
//This is where I don't know how to store the odd numbers
}
else {
//And the even numbers here as well
}
}
printf("%c,the numbers you have entered are broken down as follows:\n",name);
printf("You entered %d even numbers with a total value of \n", even);
printf("You entered %d odd numbers with a total value of \n", odd);
return 0;
}
Here is a sample program. Enhance as required as suggested in the previous update.
#include <stdio.h>
#include <stdlib.h>
int
main ()
{
int number, even, odd;
int *evenarr, *oddarr;
int evencount = 0, oddcount = 0;
int i;
char name;
evenarr = (int *) malloc(100 * sizeof(int));
oddarr = (int *) malloc(100 * sizeof(int));
printf ("Enter numbers within 1-100");
printf ("Enter 0 to quit");
do
{
scanf ("%d", &number);
if (number != 0)
{
if (number < 1 || number > 100)
continue;
if (number % 2 == 1)
{
//This is where I don't know how to store the odd numbers
printf ("odd\n");
oddarr[oddcount] = number;
oddcount++;
/* Realloc the arr if size exceed 100 */
}
else
{
//And the even numbers here as well
printf ("even\n");
evenarr[evencount] = number;
evencount++;
/* Realloc the arr if size exceed 100 */
}
}
}
while (number != 0);
for(i=0; i<oddcount; i++)
printf("odd : %d\n", oddarr[i]);
for(i=0; i<evencount; i++)
printf("even : %d\n", evenarr[i]);
}
Your question is a little ambiguous but it seems to me that you may need to allocate memory dynamically for storage since you don't know how many numbers will be entered during run time.
This can be done multiple ways. The first method involves using the malloc() and realloc() functions. I'll leave you to research these functions but basically malloc() allocates memory on the heap during run time and realloc() allows you to resize the memory that was given to you.
I think the best method would be to implement a linked list data structure. This way you can store the numbers as the user enters them and then later iterate through the list and count how many numbers were odd or even. And similarly you can also calculate their totals.
More information on linked list data structures:
https://en.wikipedia.org/wiki/Linked_list
http://www.cprogramming.com/tutorial/c/lesson15.html
https://www.youtube.com/watch?v=vcQIFT79_50
These are just some of the resources I used to learn linked lists. There are plenty more information about linked lists on Google.
You can use malloc(). It allocates memory on the heap. Also, using realloc() allows you to resize the memory you allocated using malloc().
See this tutorial on malloc and free.
The code #Umamahesh has given is correct, just that he is not freeing the memory allocated by the program, which might be fatal.
So you just free the pointers. The corrected code in #Umamahesh answer is:
#include <stdio.h>
#include <stdlib.h>
int
main ()
{
int number, even, odd;
int *evenarr, *oddarr;
int evencount = 0, oddcount = 0;
int i;
char name;
evenarr = (int *) malloc(100 * sizeof(int));
oddarr = (int *) malloc(100 * sizeof(int));
printf ("Enter numbers within 1-100");
printf ("Enter 0 to quit");
do
{
scanf ("%d", &number);
if (number != 0)
{
if (number < 1 || number > 100)
continue;
if (number % 2 == 1)
{
//This is where I don't know how to store the odd numbers
printf ("odd\n");
oddarr[oddcount] = number;
oddcount++;
/* Realloc the arr if size exceed 100 */
}
else
{
//And the even numbers here as well
printf ("even\n");
evenarr[evencount] = number;
evencount++;
/* Realloc the arr if size exceed 100 */
}
}
}
while (number != 0);
for(i=0; i<oddcount; i++)
printf("odd : %d\n", oddarr[i]);
for(i=0; i<evencount; i++)
printf("even : %d\n", evenarr[i]);
free (evenarr);
free (oddarr);
}
Also see: How do free and malloc work in C?.

Can I use malloc this way?

I want to find the minimum number and summary from a dynamic integer table. I do not know why results not shown. Have I done something wrong on the malloc ? May I use realloc too ?
#include <stdlib.h>
#include <stdio.h>
int main()
{
int n,i,min,sum,xronos;
int* array;
printf("Give me how many numbers does the table will have: \n");
scanf("%d",&n);
array=(int*)malloc(n*sizeof(int));
for(i=1;i<=n;i++)
{
printf("Give the number %d",i);
printf("\n");
scanf("%d",&array[i]);
}
for(i=1;i<=n;i++)
{
sum=sum+array[i];
if (i=1)
{
min=array[i];
}
else
{
if (array[i]<min)
{
min=array[i];
}
}
}
printf("%d",sum);
printf("\n The answer is :",(n-2)*min+(sum-min));
getch();
return 0;
}
Yes, that is almost exactly how you are supposed to use malloc, except for three small things and one big thing:
Do not cast malloc result in C,
Use indexes from zero to n-1, inclusive (your code goes from one to n, inclusive)
Add a call free(array) to avoid a memory leak.
The big thing is that you do not need malloc in order to solve this problem: you can calculate the sum and the min as you go, without saving the individual items to an array.
You can replace the chain of ifs in the loop with this check:
if (i == 0 || array[i] < min) {
min=array[i];
}
This covers both the assignment of the first element, and comparison of elements other than the first one.
Finally, you can rewrite this
sum=sum+array[i];
as
sum += array[i];
using a composite assignment operator. Don't forget to initialize the sum to zero!
#include <stdlib.h>
#include <stdio.h>
#include <errno.h> /* Defines: ENOMEM */
int main()
{
Added rCode to assist in error handling.
int rCode=0;
Removed xronos as it is not used.
int n,i,min;
Initialized sum to 0;
int sum=0;
Initialize array pointer to NULL so cleanup is easier.
int *array = NULL;
printf("Give me how many numbers does the table will have: \n");
scanf("%d",&n);
There is nothing inherently wrong with casting the output of malloc to (int *). In some situations, it is a good coding practice. (good job).
array=(int*)malloc(n*sizeof(int));
You should always test that you actually got memory from malloc.
if(NULL == array)
{
rCode=ENOMEM;
fprintf(stderr, "malloc() failed.");
goto CLEANUP;
}
The array element index is in the range of 0 through (n-1). Start indexing at zero, and be sure to stop at (n-1).
for(i=0;i<n;i++)
{
printf("Give the number %d",i);
printf("\n");
scanf("%d",&array[i]);
}
Again, the array element index is in the range of 0 through (n-1). Start indexing at zero, and be sure to stop at (n-1).
for(i=0;i<n;i++)
{
sum=sum+array[i];
if(1 == i)
min=array[i];
else
{
if(array[i] < min)
min=array[i];
}
}
printf("%d",sum);
printf("\n The answer is :",(n-2)*min+(sum-min));
getch();
CLEANUP:
From my early years, my father would tell me: 'When you bring your toys to the sandbox, always remember to put them away when you are finished.'
if(array)
free(array);
return(rCode);
}
Line 22, need
if (i=1)
set to
if (i==1)
Right now you're setting i equal to 1

Resources