Long number prime detection using Multithreading in C - c

Problem Statement: To detect whether a long integer number is a prime or not.
My Logic:
The idea is to iterate from 0 to sqrt(n). If no divisor was found between 0 to sqrt(n) then I can conclude that the number is prime and a non-prime otherwise.
Since, this needs to be multi-threaded I created a thread function called void* PrimeDetecter(void* param);. In this thread function I will iterate from startIndex to endIndex and if there was a divisor then quit the thread and write the value 1 to state true to the address of the variable isNum1Prime which is set to 0 by default.
Therefore, in the main function I need to send the number which will be checked, its start index and end index to the thread when creating the thread. So my structure will contain long int number, startIndex, endIndex, *divisor and int isPrime.
Then I create an array of size 10 of type NumberPrime because there are 10 threads and hence divide the iteration equally.
I printed the distribution of index among the threads and that works fine. Then I just create the threads and send all these elements to the thread to check whether the number is prime or not.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <math.h>
#include <pthread.h>
#define MAX_NUM_THREADS 10 // Exercise 1: Not more than 10 threads can run at a time for example.
struct NumberPrime
{
long int number, startIndex, endIndex, *divisor;
int *isPrime;
};
void *PrimeDetector(void *param)
{
struct NumberPrime parameters = *(struct NumberPrime *)param;
for (long int i = parameters.startIndex; i < parameters.endIndex; i++)
{
if (i == 0 || i == 1)
{
break;
}
else
{
if ((parameters.number % i) == 0) // if the divisor is detected then number is not a prime
{
*(parameters.divisor) = i;
*(parameters.isPrime) = 1; // change the value to true
pthread_exit(0); // exit the thread function
}
}
}
}
int main(int argc, char *argv[])
{
long int number1 = 12340000, number2 = 128;
struct NumberPrime primeData1[MAX_NUM_THREADS];
int isNum1Prime = 0; // false
long int number1Divisor = 0;
long int numberSquareRoot1 = (long int)(sqrt(number1)); // get the square root of number1
for (int i = 0; i < MAX_NUM_THREADS; i++)
{
primeData1[i].number = number1;
primeData1[i].isPrime = &isNum1Prime;
primeData1[i].divisor = &number1Divisor;
primeData1[i].startIndex = i * numberSquareRoot1 / MAX_NUM_THREADS;
primeData1[i].endIndex = ((i + 1) * numberSquareRoot1) / MAX_NUM_THREADS;
}
pthread_t primeDetectorThread1[MAX_NUM_THREADS];
int count = 0;
for (int i = 0; i < MAX_NUM_THREADS; i++)
{
if (isNum1Prime == 1)
{
pthread_cancel(primeDetectorThread1[i]);
break;
}
else
{
pthread_create(&primeDetectorThread1[i], NULL, &PrimeDetector, &primeData1[i]);
count++;
}
}
for (int i = 0; i < count; i++)
{
pthread_join(primeDetectorThread1[i], NULL);
}
isNum1Prime == 1 ? printf("Number 1 is prime.\n") : printf("Number 1 is not prime and divisible by %ld\n", number1Divisor);
return EXIT_SUCCESS;
}
The expected output is that the number is not a prime. But no matter what number I choose I always get that the number is prime.

The line if ((parameters.number % i) == 0) tests whether a number is divisible by i. If it is divisible, the number is not prime, but your code goes on to set *(parameters.isPrime) = 1; and end the thread.

Related

printing prime numbers between 0 and 100 in C

I'm trying to print prime numbers between 0 and 100 but my code ends up giving 2,3 and every number from 5 to 99. What am I doing wrong?
#include <stdio.h>
#include<math.h>
void main()
{
int n=0,i=2,flag;
while(n<=100){
if(n<2){flag=0;}
else if(n==2 || n==3){printf("%d\n",n);}
else{
while(i<=sqrt(n)){
if(n%i==0){flag=0;break;}
else{flag=1;}
i++;//at this point no. is prime
}
if(flag==1){printf("%d\n",n);}
}
n++;
}
}
Rather than testing inside the loop for n==2 || n==3, you should just print the values 2 and 3 outside the loop, and start the loop at 5. Since no even numbers are prime after 2, only test odd numbers starting at 5. And you need to start testing for factors starting at i=3 (since you know they're not even you don't have to test 2). And you shouldn't check the value of flag (for primality) until the i-loop is done.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("2\n3\n");
for (int n = 5; n <= 100; n+= 2) {
int flag = 1;
for (int i = 3; i <= sqrt(n); ++i) {
if (n % i == 0) {
flag = 0;
break;
}
}
if (flag == 1)
printf("%d\n",n);
}
}

C program to find integer closest to 10

I am writing a program that will take any number of integers. The program will end when the terminal 0 has been entered. It will then output the number closest to 10 (except for the terminal character). If there are several numbers closest to 10 then it should output the last number entered.
My current code does read the numbers from the input stream, but I don't know how to implement the logic so that the program will give me the number that is closest to 10.
I know, that I need to keep track of the minimum somehow in order to update the final result.
#include <stdio.h>
int main() {
int n = 1;
int number = 1;
int numberArray[n];
int resultArray[n];
int min;
int absMin;
int result;
int finalResult;
while (number != 0) {
scanf("%d", &number);
numberArray[n] = number;
n++;
}
for (int i = 0; i < n; i++) {
min = 10 - numberArray[i];
if (min < 0) {
absMin = -min;
}
else {
absMin = min;
}
resultArray[i] = absMin;
result = resultArray[0];
if (resultArray[i] < result) {
finalResult = resultArray[i];
}
}
printf("%d\n", finalResult);
return 0;
}
here's a simple code I wrote
One thing I must say is you can't simply declare an array with unknown size and that's what you have done. Even if the no. of elements can vary, you either take input the number of elements from the user OR (like below) create an array of 100 elements or something else according to your need.
#include <stdio.h>
#define _CRT_NO_WARNINGS
int main() {
int n = 0;
int number = 1;
int numberArray[100];
int resultArray[100];
int minNumber;
int *min;
do {
scanf("%d", &number);
numberArray[n] = number;
n++;
}
while (number != 0);
resultArray[0] = 0;
min = &resultArray[0];
minNumber = numberArray[0];
for (int i = 0; i < n-1; i++) {
if(numberArray[i]>=10){
resultArray[i] = numberArray[i] - 10;
}
if(numberArray[i]<10){
resultArray[i] = 10 - numberArray[i];
}
if(resultArray[i] <= *min){
min = &resultArray[i];
minNumber = numberArray[i];
}
}
printf("\n%d",minNumber);
return 0;
}
I have improved your script and fixed a few issues:
#include <stdio.h>
#include <math.h>
#include <limits.h>
int main()
{
int n;
int number;
int numberArray[n];
while (scanf("%d", &number) && number != 0) {
numberArray[n++] = number;
}
int currentNumber;
int distance;
int result;
int resultIndex;
int min = INT_MAX; // +2147483647
for (int i = 0; i < n; i++) {
currentNumber = numberArray[i];
distance = fabs(10 - currentNumber);
printf("i: %d, number: %d, distance: %d\n", i, currentNumber, distance);
// the operator: '<=' will make sure that it will update even if we already have 10 as result
if (distance <= min) {
min = distance;
result = currentNumber;
resultIndex = i;
}
}
printf("The number that is closest to 10 is: %d. It is the digit nr: %d digit read from the input stream.\n", result, resultIndex + 1);
return 0;
}
Reading from the input stream:
We can use scanf inside the while loop to make it more compact. Also, it will loop one time fewer because we don't start with number = 1 which is just a placeholder - this is not the input - we don't want to loop over that step.
I used the shorthand notation n++ it is the post-increment-operator. The operator will increase the variable by one, once the statement is executed (numberArray entry will be set to number, n will be increased afterwards). It does the same, in this context, as writing n++ on a new line.
Variables:
We don't need that many. The interesting numbers are the result and the current minimum. Of course, we need an array with the inputs as well. That is pretty much all we need - the rest are just helper variables.
Iteration over the input stream:
To get the result, we can calculate the absolute distance from 10 for each entry. We then check if the distance is less than the current minimum. If it is smaller (closer to 10), then we will update the minimum, the distance will be the new minimum and I have added the resultIndex as well (to see which input is the best). The operator <= will make sure to pick the latter one if we have more than one number that has the same distance.
I have started with the minimum at the upper bound of the integer range. So this is the furthest the number can be away from the result (we only look at the absolute number value anyway so signed number don't matter).
That's pretty much it.

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.

Finding Twin Primes - Have logic finished, but it won't print anything when the program is ran

A twin prime is a prime number that is exactly two larger than the largest prime number that is smaller than it. For example, 7 is a twin prime because it is exactly two larger than 5. But 17 is not a twin prime because the largest prime less than 17 is 13.
My logic for this program is as follows:
*ask number of twin primes that want to be found
*loop until desired number of twin primes are found
*loop numbers 2 - 1million (declared as variable j)
*check if that number 'j' is prime - if so flag it
*if 'j' is not flagged, subtract 2 from 'j' (call that new number 'TPcheck')
*Check if 'TPcheck' is a prime, if so, print 'TPcheck' and the first number 'j'
When I run this program, I enter the number of twin primes to be found, but it just continues to run, and doesn't print anything on the screen. I think that the problem may have something to do with the order of the loops and if statements(or maybe the way that they are nested), but I have tried a ton of different ways and nothing has worked.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i = 2, count = 0, TPcheck, j, k, flag;
int numberofTwinPrimes;
printf("Enter how many twin primes you want to find");
scanf("%d", &numberofTwinPrimes);
while(count < numberofTwinPrimes)
{
for(j = 2; j <= 1000000; ++j)
{ for(i = 2; i < j; ++i)
{
if(j%i == 0)
{
flag = 1;
continue;
}
if(flag == 0)
{
TPcheck = j - 2;
for(k = 2; k < TPcheck; ++k)
{
if(TPcheck%k == 0)
{
flag = 1;
continue;
}
if(flag == 0)
{
printf("%d\t %d\t", TPcheck, j);
count++;
}
}
}
}
}
}
return 0;
}
I think your code can be simplified quite a bit.
Define a function that simply returns whether a number is a prime number or not.
Use that in a loop using a very simple logic.
Here's a working version.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int isPrime(int n)
{
int stop = 0;
int i = 0;
// Special case for 3.
if ( n == 3 )
{
return 1;
}
// If n is not divisible by numbers up to sqrt(n),
// then, n is a prime number.
stop = (int)(sqrt(n));
// We can start at 3 and increment by 2
// There is no point dividing by even numbers.
for ( i = 3; i <= stop; i +=2 )
{
if ( n%i == 0 )
{
// It is not a prime number.
return 0;
}
}
// Checked divisibility by all numbers up to sqrt(n)
// This is a prime number.
return 1;
}
int main()
{
int i = 0;
int count = 0;
int numberofTwinPrimes;
printf("Enter how many twin primes you want to find: ");
scanf("%d", &numberofTwinPrimes);
// Start checking at 3 and increment by 2.
// There is no point checking even numbers.
// When we find the required number of twin primes, stop.
for(i = 3; i <= 1000000 && count < numberofTwinPrimes; i += 2 )
{
if ( isPrime(i) && isPrime(i+2) )
{
++count;
printf("%d\t %d\n", i, i+2);
}
}
return 0;
}
Here's the output when numberOfTwinPrimes is 10.
3 5
5 7
11 13
17 19
29 31
41 43
59 61
71 73
101 103
107 109
This isPrime() function is faster than Fumu's suggestion:
/* function isPrime returns True if argument is prime number. */
boolean isPrime(int aNumber)
{
int i;
int limit;
/* Numbers < 2 */
if(aNumber < 2) { return False; }
/* Even numbers. */
if (aNumber % 2 == 0) { return aNumber == 2; }
/* Odd numbers. */
/* Only need to check odd divisors as far as the square root. */
limit = (int)(sqrt(aNumber));
for (i = 3; i <= limit; i += 2)
{
if( aNumber % i == 0) { return False; }
}
/* Only prime numbers make it this far. */
return True;
}
Two is the only even prime, so all even numbers can be dealt with very quickly. Odd numbers only need to be tested with odd divisors less than or equal to the square root of the number: 9 = 3 * 3
There are faster methods, but they require construction of a table of primes. For your program, something like this appears to be sufficient.
Your code for checking a number is prime or not is not correct.
You should check the number never be divided any numbers less than the number.
Code of a function for checking a numer is prime or not is as follows:
/* function isPrime returns True if argument is prime number. */
boolean isPrime(int aNumber)
{
int i;
if(aNumber < 2) { return False; }
else if (aNumber==2) {return True;}
for i=2 to aNumber-1
{
if((aNumber%i) == 0){
return False;
}
}
return True;
}
I hope this give you some useful idea.

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