C program to find the n'th prime number- - c

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int prime(long long int);
long long int *arr; //array to hold n prime numbers
int main()
{
int i,count=4;;
long long int n;
scanf("%lli",&n);
arr=malloc(sizeof(long long int)*n);
arr[0]=2;
arr[1]=3;
arr[2]=5;
arr[3]=7;
if (n==1) printf("%lli",arr[0]);
else{ if (n==2) printf("%lli",arr[1]);
else{ if (n==3) printf("%lli",arr[2]);
else{ if (n==4) printf("%lli",arr[3]);
else
{
for(i=2;count<n;i++)
{
if(prime(6*i-1)) { /*As prime nos are always 6k+1 or
arr[count]=6*i-1; 6k-1fork>=2 I checked only for those*/
count++; }
if(prime(6*i+1)&&count<=n) {
arr[count]=6*i+1;
count++; }
}
printf("%lli",arr[count]);
}}}}
//free(arr);
return 0;
}
int prime(long long int x)
{
int j=1,flag=1;
while(arr[j]<=sqrt(x))
{
if (x%arr[j]==0)
{
flag=0;
break;
}
j++;
}
return flag;
}
The code is working only for n=1,2,3,4, i.e i=0,1,2,3 for which the values are explicitly given. For n=5 onwards it is giving 0 as O/P
There is some glitch related to the global dynamic array as free(arr) is giving core dump error.
Q: Is this the right way to declare a global dynamic array? What could be the problem in this code?
Thank You in advance.

If that is your actual code you have 4 bugs:
2 line comment scopes out a line of your code
the second if should check count < n not count <= n as if count == n you cannot write to arr[count]
You cannot print arr[count] only arr[count-1] which is probably what you mean
In the case where n is less than 4 you still set arr[1], arr[2] and arr[3] which may be out of bounds
It is of course also inefficient to call sqrt(x) in every loop iteration, potentially you should call it outside and there may be a potential rounding issue bug due to the way square roots are calculated, so you might prefer:
while( arr[j] * arr[j] < x )
It would be preferable not to make this global and to pass it into your function.
It would also be preferable to move the main loop logic of your program outside of main().
I'm surprised you say you program works for n=1, 2 and 3 as it looks like you are setting out of bounds.

Your counter goes beyond the size of the array. Specifically both conditions (6i-1 and 6i+1) are met for i=2, and therefore counter is incremented twice, resulting in using arr[5] where you only allocated 5 places in the array. This is because you check counter<=n and not counter
Not sure this could be also be the reason for free creating a core dump, but it is possible (because once corrupting the memory, free may access corrupted data).

Related

Non-deterministic output of simple C program

This is an unfinished program I'm writing to learn C (only checks multiples of 2 currently...)
Ultimately, I want this to be an implementation of the Sieve of Eratosthenes (prime numbers)
The problem I'm having is that the output is non-deterministic: sometimes the output includes 11, other times it does not - This happens for a handful of numbers. I have experimented by changing a few things, such as actually initializing the array of booleans to false.
Any ideas why this might be happening?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
int initialPrimeIterator = 2;
_Bool compositePrimeNumbers[n];
printf("Prime Numbers from 2 -> %d\n", n);
for (int i = initialPrimeIterator; i < n; i += initialPrimeIterator) {
compositePrimeNumbers[i-1] = true;
}
printf("Done...\n");
printf("Printing prime numbers from 2-> %d\n", n);
for (int i = 2; i < n; i++) {
if (!compositePrimeNumbers[i]){
printf("%d\n", i + 1);
}
}
return 0;
}
edit: haha. Just realized I have an array named 'compositePrime...' Should just be 'compositeNumbers'
Since I understand you are aiming at completing the program when overcoming this hurdle, I will not post a completed program, but only point out issues in your current version:
As it has been noted, the array compositePrimeNumbers is uninitialized. Since it must be initialized with all values false which is represented by 0, the quickest way is this:
memset(compositePrimeNumbers, 0, sizeof(compositePrimeNumbers));
You should not mark the current initialPrimeIterator as a composite number, hence the for-loop should start with the next multiple. Also, n must be included:
for (int i = 2 * initialPrimeIterator; i <= n; i += initialPrimeIterator) {
(actually, this can be optimized by replacing 2 * initialPrimeIterator with initialPrimeIterator * initialPrimeIterator).
With these changes, I believe you are well on the way to complete the program.
In C, a local array is not initialized, probably for performance reasons.
One way to fix this is to loop over it to set each element to false.

Why does c print a different array the second time it's printed?

My cousin has a school project and we can't figure out why is the array different the second time it's printed when there is no values changing in between?
Basically you enter a number which states how many rows/columns will the matrix have, and during first loop he assigns a number to every position and prints out the random number. However, the second time we go through the matrix the numbers are different and it seems that they are copied through the matrix from bottom left corner to top right corner for some reason. It seems strange to us because we never assign a different value to a position in the array after defining it for the first time.
int i,j,n,matrica[i][j],suma=0;
srand(time(NULL));
printf("\nunesi prirodan broj N[3,20] = \n");
scanf("%d",&n);
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
matrica[i][j]=rand()%100;
printf("%d, %d = %4d ",i, j, matrica[i][j]);
if(j==n-1) {
printf("\n");
}
}
}
printf("\n");
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
printf("%d, %d = %4d ", i, j, matrica[i][j]);
if(j==n-1) {
printf("\n");
}
}
}
And here is the result of this (the code I pasted here has 2 prints, and in the image there is 3 but every time you go through the matrix after the first time it's going to be the same):
We need to use malloc to allocate the dynamic amount of memory.
After
scanf("%d",&n) // PS You should check the return value - read the manual page
Put
matrica = malloc(sizeof(int) * n * n);
And declare it as
int *matrica;
Then replace
matrica[i][j]
with
matrica[i * n + j]
And after you have finished with matrica - use free i.e.
free(matrica);
int i,j,n,matrica[i][j]
At this point I must ask, what value do you think i and j will have? Right there you're invoking undefined behaviour by referring to variables declared with automatic storage duration which you've not initialised. Anything after this point is... undefined behaviour.
Having said that, I noticed a few other parts that look strange. Which book are you reading? The reason I ask is that the people I know to be reading reputable textbooks don't have these problems, thus your textbook (or resource, whatever) mustn't be working for you...
I can't read the commentary inside of the string literals, which is a shame, since that's usually quite valuable contextual information to have in a question. Nonetheless, moving on, if this were me, I'd probably declare a pointer to an array n of int, after asking for n, like so:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t n;
printf("Enter n, please: ");
fflush(stdout);
if (scanf("%zu", &n) != 1 || n == 0 || SIZE_MAX / n < n) {
puts("Invalid input or arithmetic overflow...");
return -1;
}
int (*array)[n] = malloc(n * sizeof *array);
if (!array) {
puts("Allocation error...");
return -1;
}
/* now you can use array[0..(n-1)][0..(n-1)] as you might expect */
free(array);
}
This should work for quite high numbers, much higher than int array[n][n]; would in its place... and it gives you that option to tell the user it was an "Allocation error...", rather than just SIGSEGV, SIGILL, SIGBUS or something...
... but nothing would be more optimal than just saving the seed you use to generate the random numbers, and the user input; that's only two integers, no need for dynamic allocation. There's no point storing what rand generates, amd you realise this, right? rand can generate that output purely using register storage, the fastest memory commonly available in our processors. You won't beat it with arrays, not meaningfully, and not... just not.

C program stops responding for large inputs

I am (re-)learning C and in the book I am following we are covering arrays, and the book gives an algorithm for finding the first n primes; myself being a mathematician and a decently skilled programmer in a few languages I decided to use a different algorithm (using the sieve of Eratosthenes) to get the first n primes. Well making the algorithm went well, what I have works, and even for moderately large inputs, i.e. the first 50,000 primes take a bit to run as you would expect, but no issues. However when you get to say 80,000 primes pretty much as soon as it begins a window pops up saying the program is not responding and will need to quit, I made sure to make the variables that take on the primes were unsigned long long int, so I should still be in the acceptable range for their values. I did some cursory browsing online and other people that had issues with large inputs received the recommendation to create the variables outside of main, to make them global variables. I tried this for some of the variables that I could immediately put outside, but that didn't fix the issue. Possibly I need to put my arrays isPrime or primes outside of main as well? But I couldn't really see how to do that since all of my work is in main.
I realize I should have done this with separate functions, but I was just writing it as I went, but if I moved everything into separate functions, my arrays still wouldn't be global, so I wasn't sure how to fix this issue.
I tried making them either static or extern, to try and get them out of the stack memory, but naturally that didn't work since they arrays change size depending on input, and change over time.
the code is:
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
unsigned long long int i,j;
unsigned long long int numPrimes,numPlaces;
int main(void)
{
bool DEBUG=false;
printf("How many primes would you like to generate? ");
scanf("%llu",&numPrimes);
// the nth prime is bounded by n*ln(n)+n*ln(ln(n)), for n >=6
// so we need to check that far out for the nth prime
if (numPrimes>= 6)
numPlaces = (int) numPrimes*log(numPrimes)+
numPrimes*log(log(numPrimes));
else
numPlaces = numPrimes*numPrimes;
if(DEBUG)
printf("numPlaces: %llu\n\n", numPlaces);
// we will need to check each of these for being prime
// add one so that we can just ignore starting at 0
bool isPrime[numPlaces+1];
// only need numPrimes places, since that is all we are looking for
// but numbers can and will get large
unsigned long long int primes[numPrimes];
for (i=2; i<numPlaces+1;i++)
isPrime[i] = true; // everything is prime until it isn't
i=2; // represents current prime
while (i < numPlaces + 1)
{
for (j=i+1;j<numPlaces+1;j++)
{
if (isPrime[j] && j%i ==0) // only need to check if we haven't already
{
isPrime[j] = false;// j is divisibly by i, so not prime
if(DEBUG)
{
printf("j that is not prime: %llu\n",j);
printf("i that eliminated it: %llu\n\n",i);
}//DEBUG if
}//if
}//for
// ruled out everything that was divisible by i, need to choose
// the next i now.
for (j=i+1;j<numPlaces+2;j++)// here j is just a counter
{
if (j == numPlaces +1)// this is to break out of while
{
i = j;
break;
}// if j = numPlaces+1 then we are done
else if (isPrime[j]==true)
{
i = j;
if (DEBUG)
{
printf("next prime: %llu\n\n",i);
}//DEBUG if
break;
}//else if
}// for to decide i
}//while
// now we have which are prime and which are not, now to just get
// the first numPrimes of them.
primes[0]=2;
for (i=1;i<numPrimes;i++)// i is now a counter
{
// need to determine what the ith prime is, i.e. the ith true
// entry in isPrime, 2 is taken care of
// first we determine the starting value for j
// the idea here is we only need to check odd numbers of being
// prime after two, so I don't need to check everything
if (i<3)
j=3;
else if (i % 2 ==0)
j = i+1;
else
j = i;
for (;j<numPlaces+1;j+=2)// only need to consider odd nums
{
// check for primality, but we don't care if we already knew
// it was prime
if (isPrime[j] && j>primes[i-1])
{
primes[i]=j;
break;
}//if, determined the ith prime
}//for to find the ith prime
}//for to fill in primes
// at this point we have all the primes in 'primes' and now we just
// need to print them
printf(" n\t\t prime\n");
printf("___\t\t_______\n");
for(i=0;i<numPrimes;i++)
{
printf("%llu\t\t%llu\n",i+1,primes[i]);
}//for
return 0;
}//main
I suppose I could just avoid the primes array and just use the index of isPrime, if that would help? Any ideas would help thanks!
Your problem is here, in the definition of the VLA ("Variable Length Array", not "Very Large Array")
bool isPrime[numPlaces+1];
The program does not have enough space in the area for local variables for the array isPrime when numPlaces is large.
You have two options:
declare the array with a "big enough" size outside of the main function and ignore the extra space
use another area for storing the array with malloc() and friends
option 1
#include <stdio.h>
unsigned long long int i,j;
bool isPrime[5000000]; /* waste memory */
int main(void)
option 2
int main(void)
{
bool *isPrime;
// ...
printf("How many primes would you like to generate? ");
scanf("%llu",&numPrimes);
// ...
// we will need to check each of these for being prime
// add one so that we can just ignore starting at 0
isPrime = malloc(numPrimes * sizeof *isPrime);
// ... use the pointer exactly as if it was an array
// ... with the same syntax as you already have
free(isPrime);
return 0;
}
The array you allocate is a stack variable (by all likelihood), and stack size is limited, so you are probably overwriting something important as soon as you hit a certain size threshold, causing the program to crash. Try using a dynamic array, allocated with malloc, to store the sieve.

Convolution in C without Stackoverflow

I'm trying to do a convolution algorithm in C but is stacking on the array of convolution.
#include <stdio.h>
#include <math.h>
#include <stddef.h>
#define convtotal 2590
int main(int argc, char *argv[]) {
int m,n,i,j;
double x[convtotal],h[convtotal];
m=sizeof(x)/sizeof(double);
n=sizeof(h)/sizeof(double);
double aux1[convtotal], aux2[convtotal],conv[convtotal][1];
for (i=0;i<n+m;i++){
if (i<n)
aux1[i]=x[i];
else
aux1[i]=0;
if (i<m)
aux2[i]=h[i];
else
aux2[i]=0;
}
for (i=0;(n+m-1);i++){
conv[i][1]=0;
for (j=0;j<m;j++)
if (i-j+1>0)
conv[i][1]=conv[i][1]+(aux1[j]*aux2[i-j+1]);
}
}
Any suggestions for this problem?
Two problems:
for (i=0;(n+m-1);i++)
You're not limiting i to anything, so the loop doesn't exit when you reach the end of your arrays; it just keeps incrementing i until you hit memory you don't own, at which point you get the segfault. Since conv only goes to m or n, I think you meant to write
for (i = 0; i < n; i++)
Secondly, you declared conv as an Nx1 array, meaning the only legal index in the second dimension may be 0, so the lines
conv[i][1] = 0;
and
conv[i][1]=conv[i][1]+(aux1[j]*aux2[i-j+1]);
should be
conv[i][0] = 0;
and
conv[i][0]=conv[i][0]+(aux1[j]*aux2[i-j+1]);
Not sure why you declared an Nx1 array (seems you could have just declared conv with one dimension), but I may be missing something obvious.
Note that your x and h arrays initially contain random values.
for (i=0;(n+m-1);i++){
conv[i][1]=0;
for (j=0;j<m;j++)
if (i-j+1>0)
conv[i][1]=conv[i][1]+(aux1[j]*aux2[i-j+1]);
}
(n+m-1) infinite loop with constant as a stop condition.
Not actually infinite, runs untill it segfaults.
for (i=0;(n+m-1);i++){
Shouldn't it be i < m+ n - 1?

Please help. The program for generating random numbers is not working

I am writing a program which have to generate N random not repeating numbers
the prototype should be voidrandom_int(int array[], int N);
it is not having any errors but it is not working. Not even giving any number
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void random_init(int array[], int N)
{
srand(time(NULL));
int i, j;
array[0]=rand()%N;
for(i=1;i<N;i++)
{
array[i]=rand()%N;
if(array[i]==0)
array[i]=1;
for(j=0;j<i;j++)
{
if(array[i]==array[j])
break;
}
if((i-j)==1)
continue;
else
i--;
}
}
int main(void)
{
int a[5], i, N;
N=5;
random_init(a,N);
for(i=0;i<N;i++)
printf("%d ", a[i]);
return 0;
}
This part makes no sense:
if(array[i]==0)
array[i]=1;
It will limit your choices to N-1 numbers (1 to N-1), out of which you try to find N numbers without repetition - leading to an infinite loop.
if((i-j)==1)
continue;
Here you probably want if (i==j) instead, to check if the previous loop ran to completion.
A faster and simpler way to generate the numbers 0..N-1 in a random order, is to put these numbers in an array (in sequential order), and then use Fisher-Yates Shuffle to shuffle the array.
This method is biased. Do not use it other than for educational purposes.
Other than Ficher-Yates, which uses another array, you can use the method of going through all the available numbers and find a "random" spot for them (effectively "initializing" the array twice). If the spot is taken, choose the next one. Something like this, in pseudo-code:
fill array with N
for all numbers from 0 to N-1
find a random spot
while spot is taken (value is N) consider next spot /* mind wrapping */
set value in current spot

Resources