Prime Finder in C - c

My prime finder is based on the fact that to check if a number is prime, we only need to check the prime numbers up to it's square root. So, to find every prime number between 0 and x, knowing all the prime numbers between 0 and x's square root will allow us to compute things very quickly. This initial list of prime finders we find using the brute force method, then we pass this list into the quick prime finder.
This code compiles and works correctly, but for some reason I'm getting segmentation fault 11 when I try an upper bound of 5 million or more. It seems to be "all good" until I try to make the "finalPrimes" list. Any thoughts as to why this might be/general feedback is greatly appreciated.
PS, I'm new to C so general commentary on my design is appreciated as well.
#include<stdio.h>
#include<math.h>
#include<stdbool.h>
void fill_array_with_primes_brute(int *array, int upper);
void fill_array_with_primes_quick(int *initial, int *final, int lower, int upper);
int find_end(int *array, int length);
bool is_prime_brute(int num);
bool is_prime_quick(int *primes, int num);
int main(void)
{
int upperBound;
printf("Enter upper bound: \n");
scanf("%i", &upperBound); /* get user input for upper bound */
int boundRoot = (int) sqrtf((float) upperBound) + 1; /* get the root of this upper bound for later use */
printf("%i is root\n", boundRoot);
printf("All good\n");
int initialPrimes[boundRoot / 2]; /* we can safely assume that the number of primes between 0 and x is less than x / 2 for larger numbers */
printf("All good\n");
int finalPrimes[upperBound / 2];
printf("All good\n");
fill_array_with_primes_brute(initialPrimes, boundRoot);
printf("All good\n");
int initialPrimesSize = find_end(initialPrimes, sizeof initialPrimes / sizeof initialPrimes[0]);
printf("All good\n");
printf("%i primes between 0 and %i\n", initialPrimesSize, boundRoot);
printf("All good\n");
initialPrimes[initialPrimesSize] = 50000;
printf("All good\n");
printf("\nHere they are: \n"); /* This will act as a barrier between the primes and the trailing 0's so that is_prime_quick works properly */
for (int x = 0; x < initialPrimesSize; x++)
{
printf("%i\n", initialPrimes[x]);
}
fill_array_with_primes_quick(initialPrimes, finalPrimes, boundRoot, upperBound);
printf("\nHere are the other ones: \n");
int pos = 0;
while (finalPrimes[pos] != 0)
{
printf("%i\n", finalPrimes[pos]);
pos++;
}
}
void fill_array_with_primes_brute(int *array, int upper) /* upper is the number up to which we want primes */
{
array[0] = 2;
array[1] = 3; /* fill array with 2 & 3 cos yolo */
int arrayCount = 2; /* start this counter cos C doesn't have ArrayLists */
for (int pote = 4; pote < upper; pote++) /* every number in range is potentially a prime */
{
if (is_prime_brute(pote))
{
array[arrayCount] = pote;
arrayCount++;
}
}
}
bool is_prime_brute(int num)
{
for (int x = 2; x < (int) sqrtf((float) num) + 1; x++) /* go through numbers up to the number's square root looking for a factor */
{
if (num % x == 0)
{
return false; /* has a factor, so not a prime */
}
}
return true; /* if we've made it this far it's a prime */
}
void fill_array_with_primes_quick(int *initial, int *final, int lower, int upper)
{
int arrayCount = 0;
for (int pote = lower; pote < upper; pote++)
{
if (is_prime_quick(initial, pote))
{
final[arrayCount] = pote;
arrayCount++;
}
}
}
bool is_prime_quick(int *primes, int num)
{
int pos = 0;
while (primes[pos] < (int) sqrtf((float) num) + 1) /* while the number we're at in the array is less than the number's square root */
{
if (num % primes[pos] == 0)
{
return false;
}
pos++;
}
return true;
}
int find_end(int *array, int length) /* Find the true end of the array, as it will contain a few trailing 0's */
{
for(int x = 0; x < length; x++)
{
if (array[x] == 0)
{
return x;
}
}
return 0;
}

This happens because you allocate too much memory in the automatic memory area (also known as "on the stack").
Replace these declarations with mallocs:
int initialPrimes[boundRoot / 2];
int finalPrimes[boundRoot / 2];
become
int *initialPrimes = malloc(sizeof(int)*boundRoot / 2);
int *finalPrimes = malloc(sizeof(int)*boundRoot / 2);
Also replace sizeof initialPrimes / sizeof initialPrimes[0]) expression with boundRoot / 2. Also add calls to free for both allocated arrays: after the final while loop in main, add
free(initialPrimes);
free(finalPrimes);

The square root of 5m is about 2236, so it is a stack overflow. Your code seems to be safe though, so the segmentation fault isn't caused by any undefined behavior:
Enter upper bound:
5000000
2237 is root
All good
All good
ASAN:DEADLYSIGNAL
=================================================================
==24998==ERROR: AddressSanitizer: stack-overflow on address 0x7ffe01f4fb28 (pc 0x55d6add011dd bp 0x7ffe028da410 sp 0x7ffe01f4fb30 T0)
#0 0x55d6add011dc in main (/tmp/a.out+0x11dc)
#1 0x7fbb442fb4c9 in __libc_start_main (/usr/lib/libc.so.6+0x204c9)
#2 0x55d6add00d19 in _start (/tmp/a.out+0xd19)
SUMMARY: AddressSanitizer: stack-overflow (/tmp/a.out+0x11dc) in main
==24998==ABORTING
As #dasblinkenlight mentioned, you may fix it using heap allocation. However, also consider one of the primality test algorithm, which is way faster and more scalable, but some aren't proved to be 100% correct (it's actually used for crypto).

The crash happens here: int finalPrimes[upperBound / 2]; when you declare and define automatic variable length array.
VLA resides on the stack, and stack space is relatively small.
To solve the problem, you should manually allocate space on the heap using malloc instead.
int* initialPrimes = malloc(sizeof(int)*(upperBound / 2));
int* finalPrimes = malloc(sizeof(int)*(upperBound / 2));
and when you are done with them, don't forget to free the memory.
Note that if you declare the array as global variables (with some constant yet big size) then the compiler will allocate them for you.
For instance the following is declaration make the crash vanish:
int finalPrimes[5000001];
int initialPrimes[5000001];
int main(void){
....

Related

How to Improve this piece of C Code- Code Wars question on Prime Gaps

I'm currently learning C and have been practicing on codewars recently. I came across this question on prime gaps and was curious on how to improve it. I was initially fooled in thinking this wouldn't be as bad but I realized that finding primes is difficult (especially for large numbers where it can be at least an NP-Hard problem). I know my code right now has multiple for-loops and this is terrible in terms of performance. I also don't fully know the clean ways of writing C so there might be some no-nos I did (e.g. I know it's my responsibility to free up dynamically allocated memory but I tried freeing memory in the main() calling function and by freeing the first element of the allocated memory block--not sure if this is the appropriate way of freeing up a block of memory)
In general, the main function calls the prime_gap function several times. I know this code works because it was submitted successfully but any tips on writing this better (algorithmically in C)?
/* a prime gap of length "n" indicates that n-1 consecutive composite numbers exist between two primes.
* For example, the gap beween (2,3) is 1, the gap between (5,7) is 2 and the gap between (7,11) is 4.
* Our function should return the first pair of primes that satisfies the gap that we're looking for in a search between two numbers. /
There should also be no primes that exist within the gap of the first two primes that are found.
* gap(g, n, m) -> where g = gap length, n = start of search space, m = end of search space
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
long long *gap(int g, int n, int m);
bool check_prime(int, bool);
int main(int argc, const char *argv[]){
long long *check3 = gap(2,100,110);
for (int i = 0; i < 2; i++){
printf("%lld ", check3[i]);
}
free(&check3[0]);
printf("\n");
long long *check = gap(2,3,50);
for (int i = 0; i< 2; i++){
printf("%lld ", check[i]);
}
printf("\n");
free(&check[0]);
long long *check1 = gap(2,5,5);
for (int i = 0; i < 2; i++){
printf("%lld ", check1[i]);
}
free(&check1[0]);
printf("\n");
long long *check2 = gap(4,130,200);
for (int i = 0; i < 2; i++){
printf("%lld ", check2[i]);
}
free(&check2[0]);
printf("\n");
long long *check4 = gap(6,100,110);
for (int i = 0; i < 2; i++){
printf("%lld ", check4[i]);
}
free(&check4[0]);
printf("\n");
long long *gap(int g, int n, int m) {
long long *result = (long long*) malloc(sizeof(long long) *2); // dynamically allocate 2 long longs for the integer array
if (result == NULL){
perror("Not enough memory");
}
int test = 0;
static bool prime;
for (int i = n; i < m; i++) { // traverse search space
prime = true;
prime = check_prime(i, prime);
if (prime == true) { // identifies prime number
test = i + g; // add the gap value to identified prime
prime = false; // set bool to false to now check for any primes that exist between i and i+gap
for (int z = i+1; z < test; z++ ) { // check there is no prime in between the first and second (test) primes
prime = check_prime(z, prime);
if (prime == true) break;
}
if (prime != true) { // found no primes between i and i+gap
prime = true; // set bool to true to then toggle off in the check right below if i+gap is not actually prime
prime = check_prime(test, prime); // now need to check whether i+gap itself is a prime
if (prime == true) {
result[0] = i; result[1] = test;
return result;
}
}
}
}
result[0] = result[1] = 0;
return result;
}
bool check_prime(int i, bool prime){
for (int j = 2; j <= sqrt(i); j++){
if (i % j == 0) {
return false;
}
}
return true;
}
Reading you code, the following comments come to mind:
you are never freeing the space allocated by the malloc
therefore I am wondering if you really need to use malloc, a simple global variable would have been sufficient for what you are doing with it
you check_prime function has a second parameter prime that is never used
in function gap, the variable prime is indicated as static, this is not required, it could also lead to errors
from the algorithmic point of view:
your logic goes like
for i in range to check:
if i is prime
check if all the number between i and i+gap are not prime
if i+gap is prime then return the tuple(i, i+gap)
globally, you are checking several times for the same number if it is prime, since this is by far the most "expensive" operation, you should try not to
specifically, you should start by checking test before iterating over all the numbers in the range i..test.

Nth Fibonacci using pointers in C; recursive and array

I have this code so far. It works and does what I want it to. I'm wondering if I could make it better. I do not really care for user input or any other "finish touches," just want to make the code more efficient and maybe more useful for future projects.
Excessive comments are for my personal use, I find it easier to read when I go back to old projects for references and what not.
Thanks!
#include<stdio.h>
#include<stdlib.h>
void fabonacci(int * fibArr,int numberOfSeries){
int n;
//allocate memory size
fibArr = malloc (sizeof(int) * numberOfSeries);
//first val, fib = 0
*fibArr = 0;//100
fibArr++;
//second val, fib = 1
*fibArr = 1;//104
fibArr++;
//printing first two fib values 0 and 1
printf("%i\n%i\n", *(fibArr- 2),*(fibArr- 1));
//loop for fib arr
for(n=0;n<numberOfSeries -2;n++,fibArr++){
//108 looking back at 104 looking back at 100
//112 looking back at 108 looking back at 104
*fibArr = *(fibArr-1) + *(fibArr -2);
//printing fib arr
printf("%i\n", *fibArr);
}
}
int main(){
//can implm user input if want
int n = 10;
int *fib;
//calling
fabonacci(fib,n);
}
Your code is halfway between two possible interpretations and I can't tell which one you meant. If you want fibonacci(n) to just give the nth number and not have any external side effects, you should write it as follows:
int fibonacci(int n) {
int lo, hi;
lo = 0;
hi = 1;
while(n-- > 0) {
int tmp = hi;
lo = hi;
hi = lo + tmp;
}
return lo;
}
You need no mallocs or frees because this takes constant, stack-allocated space.
If you want, instead, to store the entire sequence in memory as you compute it, you may as well require that the memory already be allocated, because this allows the caller to control where the numbers go.
// n < 0 => undefined behavior
// not enough space allocated for (n + 1) ints in res => undefined behavior
void fibonacci(int *res, int n) {
res[0] = 0;
if(n == 0) { return; }
res[1] = 1;
if(n == 1) { return; }
for(int i = 2; i <= n; i++) {
res[i] = res[i-1] + res[i-2];
}
}
It is now the caller's job to allocate memory:
int main(){
int fib[10]; // room for F_0 to F_9
fibonacci(fib, 9); // fill up to F_9
int n = ...; // some unknown number
int *fib2 = malloc(sizeof(int) * (n + 2)); // room for (n + 2) values
if(fib2 == NULL) { /* error handling */ }
fibonacci(fib2 + 1, n); // leave 1 space at the start for other purposes.
// e.g. you may want to store the length into the first element
fib2[0] = n + 1;
// this fibonacci is more flexible than before
// remember to free it
free(fib2);
}
And you can wrap this to allocate space itself while still leaving the more flexible version around:
int *fibonacci_alloc(int n) {
int *fib = malloc(sizeof(int) * (n + 1));
if(fib == NULL) { return NULL; }
fibonacci(fib, n);
return fib;
}
One way to improve the code is to let the caller create the array, and pass the array to the fibonacci function. That eliminates the need for fibonacci to allocate memory. Note that the caller can allocate/free if desired, or the caller can just declare an array.
The other improvement is to use array notation inside of the fibonacci function. You may be thinking that the pointer solution has better performance. It doesn't matter. The maximum value for n is 47 before you overflow a 32-bit int, so n is not nearly big enough for performance to be a consideration.
Finally, the fibonacci function should protect itself from bad values of n. For example, if n is 1, then the function should put a 0 in the first array entry, and not touch any other entries.
#include <stdio.h>
void fibonacci(int *array, int length)
{
if (length > 0)
array[0] = 0;
if (length > 1)
array[1] = 1;
for (int i = 2; i < length; i++)
array[i] = array[i-1] + array[i-2];
}
int main(void)
{
int fib[47];
int n = sizeof(fib) / sizeof(fib[0]);
fibonacci(fib, n);
for (int i = 0; i < n; i++)
printf("fib[%d] = %d\n", i, fib[i]);
}

error with array size

I am trying to make a program that calculates the amount of prime numbers that don't exceed an integer using the sieve of Eratosthenes. While my program works fine (and fast) for small numbers, after a certain number (46337) I get a "command terminated by signal 11" error, which I suppose has to do with array size. I tried to use malloc() but I didn't get it quite right. What shall I do for big numbers (up to 5billion)?
#include <stdio.h>
#include<stdlib.h>
int main(){
signed long int x,i, j, prime = 0;
scanf("%ld", &x);
int num[x];
for(i=2; i<=x;i++){
num[i]=1;
}
for(i=2; i<=x;i++){
if(num[i] == 1){
for(j=i*i; j<=x; j = j + i){
num[j] = 0;
}
//printf("num[%d]\n", i);
prime++;
}
}
printf("%ld", prime);
return 0;
}
Your array
int num[x];
is on the stack, where only small arrays can be accommodated. For large array size you'll have to allocate memory. You can save on memory bloat by using char type, because you only need a status.
char *num = malloc(x+1); // allow for indexing by [x]
if(num == NULL) {
// deal with allocation error
}
//... the sieve code
free(num);
I suggest also, you must check that i*i does not break the int limit by using
if(num[i] == 1){
if (x / i >= i){ // make sure i*i won't break
for(j=i*i; j<=x; j = j + i){
num[j] = 0;
}
}
}
Lastly, you want to go to 5 billion, which is outside the range of uint32_t (which unsigned long int is on my system) at 4.2 billion. If that will satisfy you, change the int definitions to unsigned, watching out that your loop controls don't wrap, that is, use unsigned x = UINT_MAX - 1;
If you don't have 5Gb memory available, use bit status as suggest by #BoPersson.
The following code checks for errors, tested with values up to 5000000000, properly outputs the final count of number of primes, uses malloc so as to avoid overrunning the available stack space.
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned long int x,i, j;
unsigned prime = 0;
scanf("%lu", &x);
char *num = malloc( x);
if( NULL == num)
{
perror( "malloc failed");
exit(EXIT_FAILURE);
}
for(i=0; i<x;i++)
{
num[i]=1;
}
for(i=2; i<x;i++)
{
if(num[i] == 1)
{
for(j=i*i; j<x; j = j + i)
{
num[j] = 0;
}
//printf("num[%lu]\n", i);
prime++;
}
}
printf("%u\n", prime);
return 0;
}

exceeding 500000 with the method of Erastosthenes

i got a problem which i can't solve
I want to know all prime numbers below a given limit x. Allowing me to enter x and calculate the prime numbers using the method of Erastosthenes. Displaying the result on the screen and saving it to a text file.
Calculating the primenumbers below the x, printing them and saving them to a text file worked, the only problem i have is that x can't exceed 500000
could you guys help me?
#include <stdio.h>
#include <math.h>
void sieve(long x, int primes[]);
main()
{
long i;
long x=500000;
int v[x];
printf("give a x\n");
scanf("%d",&x);
FILE *fp;
fp = fopen("primes.txt", "w");
sieve(x, v);
for (i=0;i<x;i++)
{
if (v[i] == 1)
{
printf("\n%d",i);
fprintf(fp, "%d\n",i);
}
}
fclose(fp);
}
void sieve(long x, int primes[])
{
int i;
int j;
for (i=0;i<x;i++)
{
primes[i]=1; // we initialize the sieve list to all 1's (True)
primes[0]=0,primes[1]=0; // Set the first two numbers (0 and 1) to 0 (False)
}
for (i=2;i<sqrt(x);i++) // loop through all the numbers up to the sqrt(n)
{
for (j=i*i;j<x;j+=i) // mark off each factor of i by setting it to 0 (False)
{
primes[j] = 0;
}
}
}
You will be able to handle four times as many values by declaring char v [500000] instead of int v [100000].
You can handle eight times more values by declaring unsigned char v [500000] and using only a single bit for each prime number. This makes the code a bit more complicated.
You can handle twice as many values by having a sieve for odd numbers only. Since 2 is the only even prime number, there is no point keeping them in the sieve.
Since memory for local variables in a function is often quite limited, you can handle many more values by using a static array.
Allocating v as an array of int is wasteful, and making it a local array is risky, stack space being limited. If the array becomes large enough to exceed available stack space, the program will invoke undefined behaviour and likely crash.
While there are ways to improve the efficiency of the sieve by changing the sieve array to an array of bits containing only odd numbers or fewer numbers (6n-1 and 6n+1 is a good trick), you can still improve the efficiency of your simplistic approach by a factor of 10 with easy changes:
fix primes[0] and primes[1] outside the loop,
clear even offsets of prime except the first and only scan odd numbers,
use integer arithmetic for the outer loop limit,
ignore numbers that are already known to be composite,
only check off odd multiples of i.
Here is an improved version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sieve(long x, unsigned char primes[]) {
long i, j;
for (i = 0; i < x; i++) {
primes[i] = i & 1;
}
primes[1] = 0;
primes[2] = 1;
/* loop through all odd numbers up to the sqrt(x) */
for (i = 3; (j = i * i) < x; i += 2) {
/* skip composite numbers */
if (primes[i] == 0)
continue;
/* mark each odd multiple of i as composite */
for (; j < x; j += i + i) {
primes[j] = 0;
}
}
}
int main(int argc, char *argv[]) {
long i, x, count;
int do_count = 0;
unsigned char *v;
if (argc > 1) {
x = strtol(argv[1], NULL, 0);
} else {
printf("enter x: ");
if (scanf("%ld", &x) != 1)
return 1;
}
if (x < 0) {
x = -x;
do_count = 1;
}
v = malloc(x);
if (v == NULL) {
printf("Not enough memory\n");
return 1;
}
sieve(x, v);
if (do_count) {
for (count = i = 0; i < x; i++) {
count += v[i];
}
printf("%ld\n", count);
} else {
for (i = 0; i < x; i++) {
if (v[i] == 1) {
printf("%ld\n", i);
}
}
}
free(v);
return 0;
}
I believe the problem you are having is allocating an array of int if more than 500000 elements on the stack. This is not an efficient way, to use an array where the element is the number and the value indicates whether it is prime or not. If you want to do this, at least use bool, not int as this should only be 1 byte, not 4.
Also notice this
for (i=0;i<x;i++)
{
primes[i]=1; // we initialize the sieve list to all 1's (True)
primes[0]=0,primes[1]=0; // Set the first two numbers (0 and 1) to 0 (False)
}
You are reassigning the first two elements in each loop. Take it out of the loop.
You are initializing x to be 500000, then creating an array with x elements, thus it will have 500000 elements. You are then reading in x. The array will not change size when the value of x changes - it is fixed at 500000 elements, the value of x when you created the array. You want something like this:
long x=500000;
printf("give a x\n");
scanf("%d",&x);
int *v = new int[x];
This fixes your fixed size array issue, and also gets it off the stack and into the heap which will allow you to allocate more space. It should work up to the limit of the memory you have available.

How to check whether a no is factorial or not?

I have a problem, then given some input number n, we have to check whether the no is factorial of some other no or not.
INPUT 24, OUTPUT true
INPUT 25, OUTPUT false
I have written the following program for it:-
int factorial(int num1)
{
if(num1 > 1)
{
return num1* factorial(num1-1) ;
}
else
{
return 1 ;
}
}
int is_factorial(int num2)
{
int fact = 0 ;
int i = 0 ;
while(fact < num2)
{
fact = factorial(i) ;
i++ ;
}
if(fact == num2)
{
return 0 ;
}
else
{
return -1;
}
}
Both these functions, seem to work correctly.
When we supply them for large inputs repeatedly, then the is_factorial will be repeatedly calling factorial which will be really a waste of time.
I have also tried maintaining a table for factorials
So, my question, is there some more efficient way to check whether a number is factorial or not?
It is wasteful calculating factorials continuously like that since you're duplicating the work done in x! when you do (x+1)!, (x+2)! and so on.
One approach is to maintain a list of factorials within a given range (such as all 64-bit unsigned factorials) and just compare it with that. Given how fast factorials increase in value, that list won't be very big. In fact, here's a C meta-program that actually generates the function for you:
#include <stdio.h>
int main (void) {
unsigned long long last = 1ULL, current = 2ULL, mult = 2ULL;
size_t szOut;
puts ("int isFactorial (unsigned long long num) {");
puts (" static const unsigned long long arr[] = {");
szOut = printf (" %lluULL,", last);
while (current / mult == last) {
if (szOut > 50)
szOut = printf ("\n ") - 1;
szOut += printf (" %lluULL,", current);
last = current;
current *= ++mult;
}
puts ("\n };");
puts (" static const size_t len = sizeof (arr) / sizeof (*arr);");
puts (" for (size_t idx = 0; idx < len; idx++)");
puts (" if (arr[idx] == num)");
puts (" return 1;");
puts (" return 0;");
puts ("}");
return 0;
}
When you run that, you get the function:
int isFactorial (unsigned long long num) {
static const unsigned long long arr[] = {
1ULL, 2ULL, 6ULL, 24ULL, 120ULL, 720ULL, 5040ULL,
40320ULL, 362880ULL, 3628800ULL, 39916800ULL,
479001600ULL, 6227020800ULL, 87178291200ULL,
1307674368000ULL, 20922789888000ULL, 355687428096000ULL,
6402373705728000ULL, 121645100408832000ULL,
2432902008176640000ULL,
};
static const size_t len = sizeof (arr) / sizeof (*arr);
for (size_t idx = 0; idx < len; idx++)
if (arr[idx] == num)
return 1;
return 0;
}
which is quite short and efficient, even for the 64-bit factorials.
If you're after a purely programmatic method (with no lookup tables), you can use the property that a factorial number is:
1 x 2 x 3 x 4 x ... x (n-1) x n
for some value of n.
Hence you can simply start dividing your test number by 2, then 3 then 4 and so on. One of two things will happen.
First, you may get a non-integral result in which case it wasn't a factorial.
Second, you may end up with 1 from the division, in which case it was a factorial.
Assuming your divisions are integral, the following code would be a good starting point:
int isFactorial (unsigned long long num) {
unsigned long long currDiv = 2ULL;
while (num != 1ULL) {
if ((num % currDiv) != 0)
return 0;
num /= currDiv;
currDiv++;
}
return 1;
}
However, for efficiency, the best option is probably the first one. Move the cost of calculation to the build phase rather than at runtime. This is a standard trick in cases where the cost of calculation is significant compared to a table lookup.
You could even make it even mode efficient by using a binary search of the lookup table but that's possibly not necessary given there are only twenty elements in it.
If the number is a factorial, then its factors are 1..n for some n.
Assuming n is an integer variable, we can do the following :
int findFactNum(int test){
for(int i=1, int sum=1; sum <= test; i++){
sum *= i; //Increment factorial number
if(sum == test)
return i; //Factorial of i
}
return 0; // factorial not found
}
now pass the number 24 to this function block and it should work. This function returns the number whose factorial you just passed.
You can speed up at least half of the cases by making a simple check if the number is odd or even (use %2). No odd number (barring 1) can be the factorial of any other number
#include<stdio.h>
main()
{
float i,a;
scanf("%f",&a);
for(i=2;a>1;i++)
a/=i;
if(a==1)
printf("it is a factorial");
else
printf("not a factorial");
}
You can create an array which contains factorial list:
like in the code below I created an array containing factorials up to 20.
now you just have to input the number and check whether it is there in the array or not..
#include <stdio.h>
int main()
{
int b[19];
int i, j = 0;
int k, l;
/*writing factorials*/
for (i = 0; i <= 19; i++) {
k = i + 1;
b[i] = factorial(k);
}
printf("enter a number\n");
scanf("%d", &l);
for (j = 0; j <= 19; j++) {
if (l == b[j]) {
printf("given number is a factorial of %d\n", j + 1);
}
if (j == 19 && l != b[j]) {
printf("given number is not a factorial number\n");
}
}
}
int factorial(int a)
{
int i;
int facto = 1;
for (i = 1; i <= a; i++) {
facto = facto * i;
}
return facto;
}
public long generateFactorial(int num){
if(num==0 || num==1){
return 1;
} else{
return num*generateFactorial(num-1);
}
}
public int getOriginalNum(long num){
List<Integer> factors=new LinkedList<>(); //This is list of all factors of num
List<Integer> factors2=new LinkedList<>(); //List of all Factorial factors for eg: (1,2,3,4,5) for 120 (=5!)
int origin=1; //number representing the root of Factorial value ( for eg origin=5 if num=120)
for(int i=1;i<=num;i++){
if(num%i==0){
factors.add(i); //it will add all factors of num including 1 and num
}
}
/*
* amoong "factors" we need to find "Factorial factors for eg: (1,2,3,4,5) for 120"
* for that create new list factors2
* */
for (int i=1;i<factors.size();i++) {
if((factors.get(i))-(factors.get(i-1))==1){
/*
* 120 = 5! =5*4*3*2*1*1 (1!=1 and 0!=1 ..hence 2 times 1)
* 720 = 6! =6*5*4*3*2*1*1
* 5040 = 7! = 7*6*5*4*3*2*1*1
* 3628800 = 10! =10*9*8*7*6*5*4*3*2*1*1
* ... and so on
*
* in all cases any 2 succeding factors inf list having diff=1
* for eg: for 5 : (5-4=1)(4-3=1)(3-2=1)(2-1=1)(1-0=1) Hence difference=1 in each case
* */
factors2.add(i); //in such case add factors from 1st list " factors " to " factors2"
} else break;
//else if(this diff>1) it is not factorial number hence break
//Now last element in the list is largest num and ROOT of Factorial
}
for(Integer integer:factors2){
System.out.print(" "+integer);
}
System.out.println();
if(generateFactorial(factors2.get(factors2.size()-1))==num){ //last element is at "factors2.size()-1"
origin=factors2.get(factors2.size()-1);
}
return origin;
/*
* Above logic works only for 5! but not other numbers ??
* */
}

Resources