I have a BSP implementation in C for the Sieve Of Erastothenes, see the code below.
When executed with ./bspsieve 2 100 it however gives the following output:
"It took : 0.000045 seconds for proc 0 out of 2.
23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,"
for ./bspsieve 1 100 it gives the same, i.e:
"./bspsieve 1 100
It took : 0.000022 seconds for proc 0 out of 1.
23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,"
For ./bspsieve 8 100 (so using 8 processors) it gives a segmentation fault.
i.e
"./bspsieve 8 100
It took : 0.000146 seconds for proc 0 out of 8.
Segmentation fault (core dumped)"
This means that my bounds aren't okay I think?
It fails to find the first primes! I can't find my fault (really inexperienced with C). Except this, are there other improvements to my code you guys can suggest? The algorithm doesn't need to be fast, but any improvement in understandability and readability is welcome.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <mcbsp.h>
/*
Note: To compile, this file has to be in the same folder as mcbsp.h and you need the 2 following commands:
gcc -Iinclude/ -pthread -c -o bspsieve.o bspsieve.c
gcc -o bspsieve bspsieve.o lib/libmcbsp1.1.0.a -lpthread -lrt
*/
int procs;
int upperbound;
int *primes;
//SPMD function
void bspSieve(){
bsp_begin(procs);
int p = bsp_nprocs(); // p = number of procs obtained
int s = bsp_pid(); // s = proc number
float blocksize; // block size to be used, note last proc has a different size!
if( s != p-1){
blocksize = ceil(upperbound/p);
} else {
blocksize = upperbound - (p-1)*ceil(upperbound/p);
}
// Initialize start time and end time, set start time to now.
double start_time,end_time;
start_time = bsp_time();
// Create vector that has block of candidates
int *blockvector;
blockvector = (int *)malloc(blocksize*sizeof(int));
int q;
for(q = 0; q<blocksize; q++){
//List contains the integers from s*blocksize till blocksize + s*blocksize
blockvector[q] = q + s*blocksize;
}
//We neglect the first 2 'primes' in processor 0.
if(s == 0){
blockvector[0] = 0;
blockvector[1] = 0;
}
// We are using the block distribution. We assume that n is large enough to
// assure that n/p is larger than sqrt(n). This means that we will always find the
// sieving prime in the first block, and so have to broadcast from the first
// processor to the others.
long sieving_prime;
int i;
bsp_push_reg( &sieving_prime,sizeof(long) );
bsp_sync();
for(i = 2; i * i < upperbound; i++) {
//Part 1: if first processor, get the newest sieving prime, broadcast. Search for newest prime starting from i.
if(s == 0){
int findPrimeNb;
for(findPrimeNb = i; findPrimeNb < blocksize; findPrimeNb++) {
if( blockvector[findPrimeNb] != 0) {
sieving_prime = blockvector[findPrimeNb];
//broadcast
int procNb;
for(procNb = 0; procNb < p; ++procNb){
bsp_put(procNb, &sieving_prime,&sieving_prime,0,sizeof(long));
}
break;
}
}
}
bsp_sync();
//Part 2: Sieve using the sieving prime
int sievingNb;
for(sievingNb = 0; sievingNb < blocksize; sievingNb++){
//check if element is multiple of sieving prime, if so, pcross out (put to zero)
if( blockvector[sievingNb] % sieving_prime == 0){
blockvector[sievingNb] = 0;
}
}
}
//part 3: get local primes to central area
int transferNb;
long transferPrime;
for(transferNb = 0; transferNb < blocksize; transferNb++){
transferPrime = blockvector[transferNb];
primes[transferPrime] = transferPrime;
}
// take the end time.
end_time = bsp_time();
//Print amount of taken time, only processor 0 has to do this.
if( s == 0 ){
printf("It took : %.6lf seconds for proc %d out of %d. \n", end_time-start_time, bsp_pid(), bsp_nprocs());
fflush(stdout);
}
bsp_pop_reg(&sieving_prime);
bsp_end();
}
int main(int argc, char **argv){
if(argc != 3) {
printf( "Usage: %s <proc count> <upper bound> <n", argv[ 0 ] );
exit(1);
}
//retrieve parameters
procs = atoi( argv[ 1 ] );
upperbound = atoi( argv[ 2 ] );
primes = (int *)malloc(upperbound*sizeof(int));
// init and call parallel part
bsp_init(bspSieve, argc, argv);
bspSieve();
//Print all non zeros of candidates, these are the primes.
// Primes only go to p*p <= n
int i;
for(i = 0; i < upperbound; i++) {
if(primes[i] > 0) {
printf("%d, ",primes[i]);
fflush(stdout);
}
}
return 0;
}
Troubles may come from
blockvector[q] = q + s*blocksize;
As long as blocksize is equal to ceil(upperbound/p) on all processus, there is no problem. Since 1 and 2 are divisor of 100, your program works well.
As you wrote in your code, it is not always the case...It is not true on the last processus when calling ./bspsieve 8 100. Some values in blockvector are above 100, and a segmentation fault is likely to appear when writting in the prime array.
A way to correct this behaviour is :
blockvector[q] = q + s*ceil(upperbound/p);
(store ceil(...) to run faster.)
It might also be better to zero the prime array before using it.
I did not check wheather it works...Try it !
Bye,
Francis
Some possible issues are noted below. Note that if you had supplied a standalone, compilable example (as an external download for example) it would make it easier for someone unfamiliar with the BSP library to help you. Also noting the specific library would help (assuming it is MulticoreBSP).
I believe you are incorrectly dividing the number by itself. For example try manually tracing the first case:
i = 2
so sieving_prime = 2
2 % 2 == 0 so blockvector[2] = 0 (incorrectly saying 2 is not prime)
This issue is why you are only outputting primes starting at 23. You are looping 8 times (for (i=2; i*i<100..., 2..9). For these loops you start at the primes 2, 3, 5, 7, 11, 13, 17, 19 which incorrectly eliminates each them leaving 23 as the first prime output.
For upperbound/p when both variables are integers the division result will be an integer so that ceil(upperbound/p) probably doesn't do what you think it does. For example ceil(100/8) == 12 not 13. Cast the numbers to float if you wish the division result to be a floating point.
Related to this your last block is not being populated with numbers correctly when the last block is a different size (i.e., procs does not evenly divide upperbound). For example in the case of bspsieve 8 100 your last block starts at 112 instead of 90.
This last issue is most likely the cause of your segmentation fault since a value of 112 will overflow your primes[] array.
Fixing these issues 'should' fix the incorrect output and the crash. If you are still getting incorrect output I would add liberal printf() calls until you can see where the code differs from what it should be. I would also start testing with 1 processor first and increment this one at a time to confirm correct operation. Also test with different upper bounds.
Related
I'm making a program in C that factors any number using primes and saves these primes, multiplying them you find all the divisors of a number.
But I can't make an array that multiplies the previous columns and saves the results. follow the example
60 / 2
30 / 2
15 / 3
5 / 5
divisors = 2, 2, 3, 5
now i need`add 1 to array array {1, 2, 2, 3, 5}
i need this now start colune 2 {1, 2} 2 * 1 = 2 save.
next colune 3 {1, 2, 2} 2 * 1 = 2 but we already have 2 so don't save it.
continue 2 * 2 = 4 save.
colune 4 {1, 2, 2, 3} 3 * 1 = 3 save, 3 * 2 = 6 save, 3 * 4 = 12 save.
colune 5 {1, 2, 2, 3, 5} 5 * 1 = 5 save, 5* 2 = 10, 5 * 4 = 20 save, 5 * 3= 15 save, 5 * 6 = 30 save, 5 * 12 = 60 save.
now we found all divisors of 60 = 1, 2, 3, 4, 5, 6, 10 ,12 , 15,20, 30, 60.
It is important to mention that I need the program to be like this, I know there are other ways... but I only need this one, I have been unable to complete it for 1 week
video to help https://www.youtube.com/watch?v=p0v5FpONddU&t=1s&ab_channel=MATEM%C3%81TICAFORALLLUISCARLOS
my program so far
#include <stdlib.h>
#include <stdio.h>
int N = 1;
int verificarPrimo(int numero);
int main()
{
int num = 60, i, primo = 1, resultados[N], j = 1;
for (i = 0; i < 60; i++)
{
if (primo == 1)
{
resultados[N - 1] = primo;
i = 2;
primo = i;
}
if (verificarPrimo(i))
{
while (num % i == 0)
{
num = num / i;
resultados[N] = i;
N++;
}
}
}
for (i = 1; i < N; i++)
{
printf("%d \n", resultados[i]);
}
}
int verificarPrimo(int primo)
{
int i;
if (primo <= 1)
return 0;
for (i = 2; i <= primo / 2; i++)
{
if (primo % i == 0)
return 0;
}
return 1;
}
I tried out your code and ran into some issues with how the results were being stored. First off, the results array is being initially defined as an array with a size of "1", and that it not what you probably want.
int num = 60, i, primo = 1, resultados[N], j = 1;
With that in mind and determining the spirit of this project, following is tweaked version of the code to test for one or more values and their factors.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int verificarPrimo(int primo)
{
int sq = sqrt(primo) + 1; /* Usual checking for a prime number is from '2' to the square root of the number being evaluated */
if (primo <= 1)
return 0;
for (int i = 2; i < sq; i++)
{
if (primo % i == 0)
return 0;
}
return 1;
}
int main()
{
int N = 0;
int num = 0, entry = 0, resultados[100]; /* The results array needs to be defined with some value large enough to contain the assorted factors a number might have */
printf("Enter a number to evaluate for factors: "); /* Using a prompt to allow various values to be tested */
scanf("%d", &entry);
num = entry;
if (verificarPrimo(num)) /* Catchall in case the entered number is a prime number */
{
printf("This number is a prime number and has no factors other than one and itself\n");
return 0;
}
resultados[0] = 1; /* Normally the value '1' is implied in a list of factors, so these lines could be omitted */
N = 1;
for (int i = 2; i < entry; i++)
{
if (verificarPrimo(i))
{
while (num % i == 0)
{
num = num / i;
resultados[N] = i;
N++;
}
}
}
printf("Factors for %d\n", entry);
for (int i = 0; i < N; i++)
{
printf("%d ", resultados[i]);
}
printf("\n");
return 0;
}
Some items to point out in this tweaked code.
In the prime number verification function, it is usually customary to set up a for loop in testing for prime numbers to go from the value of "2" to the square root of the number being tested. There usually is no need travel to one half of the number being tested. For that, the #include <math.h> statement was added (FYI, "-lm" would need to be added to link in the math library).
Instead of defining the results array with a value of one element, an arbitrary value of "60" was chosen for the holding the possible number of results when evaluating factors for a given value. Your original code had the potential of storing data past the end of the array and causing a "smashing" error.
The value of "1" is usually left out of the list of factors for a number, but was left in as the initial result value. This might be left out of the completed code.
An additional entry field was added to allow for user entry to be tested to give the code some flexibility in testing numbers.
A test was also added to see if the entered number is itself a prime number, which would only have factors of "1" and itself.
Following is some sample terminal output testing out your original value of "60" along with some other values.
#Dev:~/C_Programs/Console/Factors/bin/Release$ ./Factors
Enter a number to evaluate for factors: 60
Factors for 60
1 2 2 3 5
#Dev:~/C_Programs/Console/Factors/bin/Release$ ./Factors
Enter a number to evaluate for factors: 63
Factors for 63
1 3 3 7
#Dev:~/C_Programs/Console/Factors/bin/Release$ ./Factors
Enter a number to evaluate for factors: 29
This number is a prime number and has no factors other than one and itself
Give that a try to see if it meets the spirit of your project.
I've been racking my brain on how I would be able to print my array in the format below(image)
I have done the necessary calculations in my code to have an array for the numbers {18,23,22,21...} but I'm trying to figure out a way to format them so they are under the corresponding years.
The furthest left column are the first 3 numbers of a year and the top row is the last number.
For example if this data was calculated for year starting in 2010, the numbers would start under the 0 column, and so on.
So far I could only come up with hard-coding the spaces so everything lines up, but as the year is a user input I can't figure out how to automatically have the data start under the corresponding year. I appreciate any ideas you can offer.
printf(" 0 1 2 3 4 5 6 7 8 9\n");
printf("%c%c%c\n", year1[0], year1[1], year1[2]);
printf("%c%c%c\n", year2[0], year2[1], year2[2]);
printf("%c%c%c\n", year3[0], year3[1], year3[2]);
where the indexed arrays would print the first 3 numbers of the year similar to the picture.
Since another answer has already provided a full solution, I will now provide my own full solution.
The advantage of my solution is that less if checks are necessary, because I have placed the code which jumps several columns outside the main loop. That way, it is not necessary to constantly check inside the main loop whether we must jump several columns. Also, I make more use of the control flow of the program, so that in the main loop, the only conditions that I must check for are
whether the end of the line has been reached, and
whether the end of the array has been reached.
However, the disadvantage of my solution is that my two nested for loops are harder to understand, because they have a non-standard structure.
#include <stdio.h>
void print_table( int start_year, int values[], int num_values )
{
int col;
int written = 0;
//don't print anything if array is empty
if ( num_values <= 0 )
return;
//calculate quotient and remainder of dividing
//start_year by 10
int quotient = start_year / 10;
int remainder = start_year % 10;
//print header
printf(" 0 1 2 3 4 5 6 7 8 9\n");
//prepare first line for data
printf( "%4d", quotient );
for ( col = 0; col < remainder; col++ )
{
printf( " " );
}
//process one row per loop iteration
for ( int row = 1; ; row++ )
{
//process one column per loop iteration
for ( ; col < 10; col++ )
{
printf( " %3d", values[written++] );
//check whether we have reached the end of the array
if ( written == num_values )
{
putchar( '\n' );
return;
}
}
//prepare next line for data
printf( "\n%4d", quotient + row );
col = 0;
}
}
int main( void )
{
int arr[] = {
18, 23, 22, 21, 20,
18, 24, 23, 22, 20, 19, 18, 24, 22, 21,
20, 19, 24, 23, 22
};
print_table( 2015, arr, sizeof arr / sizeof *arr );
}
This program has the following output:
0 1 2 3 4 5 6 7 8 9
201 18 23 22 21 20
202 18 24 23 22 20 19 18 24 22 21
203 20 19 24 23 22
Highlights of the code below:
The year is broken into two parts using division and modulo operators. The variable blanks, which is set to the last digit of the year, is the number of columns that need to be skipped on the first line. The variable row is the upper digits of the year, and is used as the row label.
The for loop goes through each element of the array.
The array element is printed near the middle of the body of the loop.
Before printing the array element:
When a new row is being started (col == 0), the row label is printed
When the blanks need to be displayed (blanks > 0):
print the necessary spaces
update the column number so that col reflects the current location on the line
set blanks to 0, so that this only happens once
After printing the array element:
Update the column number
When the last column is reached, output a newline and start a new row
Here's the code:
#include <stdio.h>
void showTable(int year, int array[], int length)
{
// print the column headers
printf(" 0 1 2 3 4 5 6 7 8 9\n");
// initialize some variables
int blanks = year % 10; // number of entries to skip on the first row
int row = year / 10; // upper digits of the year, used as the row label
int col = 0; // column number 0 to 9
// loop through the elements of the array
for (int i = 0; i < length; i++)
{
// print the year prefix when the column number is 0
if (col == 0)
printf("%3d", row);
// print blank spaces to reach the starting column on the first line
// this is only done once
if (blanks > 0)
{
printf("%*s", blanks * 4, "");
col += blanks;
blanks = 0;
}
// print a number from the array
printf(" %3d", array[i]);
// update the column, if we've reached the last column, start a new row
col++;
if (col > 9) {
printf("\n");
col = 0;
row++;
}
}
// output a final newline, if needed
if (col != 0)
putchar('\n');
}
int main(void)
{
int year = 2015;
int values[] = { 18, 23, 22, 21, 20, 18, 24, 23, 22, 20,
19, 18, 24, 22, 21, 20, 19, 24, 23, 22 };
showTable(year, values, sizeof(values) / sizeof(values[0]));
}
it is not correct code, but can give educational idea how to solve your task
int i = 2010;
while ()
{
if (input_year < i);
printf(" ");
else
printf("%d", calculated_data);
i++;
}
and please show your code, if you want some more ideas how to improve your code
Logic: I am trying to loop from 3 to 100 and put all prime numbers in that range in an array. I do this by first putting 2 manually into the array. After that, I loop over all the numbers and if a number is not divisible by all the prime numbers I have added to the array, it is a prime. The logic itself is not really valid in my opinion but this is a homework problem and I need to do it the way the professor wants it to be done.
So I try to loop and it gets to a point and the program just crashes. What am I doing wrong here?
int primeNums_lessThan100[25] = {2}; //25 is the size here because there are only 25 prime numbers under 100.
int primeNums_lessThan100_length = 1;
for(int counter = 3 ; counter < 100 ; counter++)
{
printf("Entered here!\n");
for(int array_idx = 0; array_idx < primeNums_lessThan100_length ; array_idx++)
{
if(counter % primeNums_lessThan100[array_idx] != 0)
{
printf("Entered here, TOO!\n");
primeNums_lessThan100[array_idx+1] = counter;
primeNums_lessThan100_length++;
}
else
{
continue;
}
}
}
You have a basic error in your logic. It's not enough to find out the counter value is coprime with some previously found prime to determine counter is prime itself. You need to test it is coprime with all primes found.
Suppose counter == 9 and you test it against the first item of your 'prime' numbers, which is 2. The result of 9 % 2 is of course 1, which is not equal zero and your program adds 9 to the array as a prime number. It happens even earlier for counter == 4 — first you find out it is divisible by 2 and reiterate the loop to find out in the next step 4 % 3 != 0 and add 4 to 'primes'.
As a further result the array overflows (you put more numbers into it than you expected and declared; actually, you put every natural number to it, because each N greater than 2 is not divisible by (N-1)), which means you eventually write past the end of the array, thus triggering an Undefined Behavior.
That displays also a basic error in the design: you do not check your array_idx against the array size, which might allow you to handle the error in some civilized manner.
the following proposed code:
cleanly compiles
performs the desired functionality
comments in code explain what is being done
note use of size_t for numbers that will never be less than 0
Note that all prior prime values are checked against the testPrime
Note that when a prime is found, it is placed in the next available entry in the array: `primeNums[]
and now, the proposed code:
#include <stdio.h> // puts(), printf()
// eliminate ''magic' numbers by giving them meaningful names
//25 is the size here because there are only 25 prime numbers under 100
#define MAX_PRIMES 25
#define TEST_LIMIT 100
int main( void )
{
// declare prime number array and init to 0
int primeNums[ MAX_PRIMES ] = {0};
// pre-set first prime number
primeNums[0] = 2;
// init number of primes found
size_t primeCount = 1;
// test all values of interest
for( int testPrime = 3 ; testPrime < TEST_LIMIT ; testPrime++ )
{
// init 'prime' indicator, 1 means value is prime
size_t Prime = 1;
for( size_t prime_idx = 0; prime_idx < MAX_PRIMES; prime_idx++ )
{
// check that array of prime values contains a valid prime
if( primeNums[ prime_idx ] )
{
if( testPrime % primeNums[ prime_idx ] == 0 )
{
// indicate not a prime number
Prime = 0;
}
}
else
{ // else, all previously found prime numbers checked
break;
} // end if
} // end for each prime already found
if( Prime )
{ // then test number was prime
// update the array of primes
primeNums[ primeCount ] = testPrime;
// update the count of primes found
primeCount++;
}
}
// display the found primes
for( size_t i = 0; i < primeCount; i++ )
{
printf( "%d, ", primeNums[i] );
}
// assure the data gets displayed on the terminal before the program exits
puts( "" );
}
a run of the proposed code results in:
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
I just have to make a simple program, where I have an array given with random numbers, then I have to do some things with the array and then print the elements at the end. But I don't know what's happening here.
First I wanted to make a code, just to print the elements and see if it works before doing anything else.
#include <stdio.h>
int main(void) {
int nums[] = {12, 3, 54, -4, 56, 4, 7, 3};
//.....
for(int i = 0; nums[i]; i++) {
printf("nums[%d] = %d\n", i, nums[i]);
}
return 0;
}
And the result was:
nums[0] = 12
nums[1] = 3
nums[2] = 54
nums[3] = -4
nums[4] = 56
nums[5] = 4
nums[6] = 7
nums[7] = 3
nums[8] = -427200144
nums[9] = 32765
I ran the code more times, and the 8th and 9th element is always kinda random... But I mean I don't even have that many numbers, what's wrong here??
Also I tried with other random numbers and sometimes it works fine...
int nums[] = {2, -10, 64, 100, 22, 4};
nums[0] = 2
nums[1] = -10
nums[2] = 64
nums[3] = 100
nums[4] = 22
nums[5] = 4
Can someone explain what's happening here?
Edit: Meanwhile I realized this method is bad, since if the number in the array is 0, then my condition is false so the for cycle stops, but I'm curious, what's happening here, so I gonna post this anyways.
I recommend
for(int i = 0; i < sizeof(nums) / sizeof(*nums); i++) {
printf("nums[%d] = %d\n", i, nums[i]);
}
sizeof(nums) is the total size of the array (in bytes).
sizeof(*nums) is size of one element of the array (in bytes).
Therefore, sizeof(nums) / sizeof(*nums) represents the number of elements and that is what should be the condition in the loop.
Another option is having a separate variable that contains number of elements in the array, but it's less convenient than the first method I described.
Hi so I am using C code and trying to create a table where the number gets incremented in multiples of 5 starting from 1 to 5 to 10 to... all the way until the user's input. What I've gotten so far is that it starts at 1 and then increases the number by 5 like 1 to 6 to 11 to 16... until it gets to where it can't increase the number by 5 anymore without going above the user's input. Could someone help me set up the for loop better?
Here's the segment of my code I'm talking about:
else //run this statement if the user inputs a number greater than 14
{
printf("Number Approximation1 Approximation2\n-----------------------------------------------------\n"); //prints the header for second table
for ( i = 1; i <= n; i += 5 )
{
printf("%d %e %e\n", i, stirling1( i ), stirling2( i )); //calls functions to input approximate factorials
}
}
So with this code if I input n as 28, I get i to increment from 1 to 6 to 11 to 16 to 21 to 26.
What I want the code to do if I input n as 28 is increment i from 1 to 5 to 10 to 15 to 20 to 25 to 28.
Thanks in advance!
Try this:
{
printf("Number Approximation1 Approximation2\n-----------------------------------------------------\n"); //prints the header for second table
printf("%d %e %e\n", i, stirling1( 1 ), stirling2( 1 ));
for ( i = 5; i <= n; i += 5 )
{
printf("%d %e %e\n", i, stirling1( i ), stirling2( i )); //calls functions to input approximate factorials
}
}
This will print values for 1, 5, 10, 15, 20... and so on
Note that, besides an extra line of code, its faster than adding an "if" inside the loop.
I added two if statements which would help you deal with the special cases of having statements printed at i = 1 and i = n besides having the statement printed every 5.
else //run this statement if the user inputs a number greater than 14
{
printf("Number Approximation1 Approximation2\n-----------------------------------------------------\n"); //prints the header for second table
for ( i = 1; i <= n; i += 5 )
{
printf("%d %e %e\n", i, stirling1( i ), stirling2( i )); //calls functions to input approximate factorials
if (i == 1){
//when it iterates at the end of this loop, i = 5.
//In your example, you will get i from 1 to 5 to 10 up to 25 etc.
i = 0;
}
if ( (i + 5) > n){
// for the next loop, it will check if i will exceed n on the next increment.
// you do not want this to happen without printing for n = i.
//In your case if n = 28, then i will be set to 23, which will then increment to 28.
i = n - 5;
}
}
}
There are probably other more elegant ways of achieving this, but this is just a simple example of what you could try.