I am having a truly bizarre problem with my code here. It works (seemingly) when I use manual print statements to output the values of int *primesArr, but if I try to do so with a for loop it fails. I ran it through gdb and find that it crashes right around where I set the next cell in the array to value 'k', which only occurs when a number is prime. The first iteration is successful (i.e. 2 is set to primesArr[0]) and then the program Segfaults when trying to increment the array. But this only happens when using a for-loop. When I create individual print statements, my program works as expected. I'm not sure how/why I am accessing memory that hasnt been appropriated when using a for-loop. I'm sure I've performed some amateur mistake somewhere, and it probably has something to do with how I'm passing my pointer... but I cannot determine its exact root. I'd appreciate any help and thank you in advance.
#include<stdio.h>
int genPrimes(int seed, int *test){
int inNumPrimes=0;
for(int k=0; k<=seed; k++){//k is number being checked for primeness
int cnt=0;
for(int i=1; i<=k; i++){//'i' is num 'k' is divided by
if(k%i == 0){
cnt++;
if(cnt > 2){
break;
}
}else{
}
}
if(cnt == 2){
printf("%i IS PRIME\n",k);
*test=k;
test++;//according to gdb, the problem is somewhere between here
inNumPrimes++;//and here. I'd wager I messed up my pointer somehow
}
//printf("%i\n",k);
}
return inNumPrimes;
}
int main(){
int outNumPrimes=0;
int *primesArr;
int n = 0;
n=20;
outNumPrimes=genPrimes(n, primesArr);
printf("Congratulations! There are %i Prime Numbers.\n",outNumPrimes);
//If you print using this for loop, the SEGFAULT occurs. Note that it does not matter how high the limit is; its been set to many values other than 5. It will eventually be set to 'outNumPrimes'
//for(int a=0; a<5; a++){
//printf("%i\n",primesArr[a]);
//}
//If you print the array elements individually, the correct value--a prime number--is printed. No SEGFAULT.
printf("%i\n",primesArr[0]);
printf("%i\n",primesArr[1]);
printf("%i\n",primesArr[2]);
printf("%i\n",primesArr[3]);
printf("%i\n",primesArr[4]);
printf("%i\n",primesArr[5]);
printf("%i\n",primesArr[6]);
printf("%i\n",primesArr[7]);
//
return 0;
}
Output with manual statements:
$ ./a.out
2 IS PRIME
3 IS PRIME
5 IS PRIME
7 IS PRIME
11 IS PRIME
13 IS PRIME
17 IS PRIME
19 IS PRIME
Congratulations! There are 8 Prime Numbers.
2
3
5
7
11
13
17
19
Now with the for loop:
$ ./a.out
2 IS PRIME
Segmentation fault
you are passing an uninitialized pointer into your primes function. the behavior you get is undefined, which is why this seems so mysterious. the variable primesArr could be pointing to anywhere.
for a simple case like this, it'd probably be better to use a std::vector<int>
The line
int *primesArr;
Declares primesArr as a pointer variable but doesn't allocate any memory for it. Since the genPrimes() function expects to treat it as an empty array that will be filled with primes, you can allocate memory in main() before calling genPrimes():
int primesArr[MAX_PRIMES];
or
int *primesArr = malloc(MAX_PRIMES * sizeof(int));
In both cases, however, you must guarantee that MAX_PRIMES is large enough to hold all of the primes that genPrimes() finds, otherwise the code will generate an error just as it does now.
Other hints:
1: Complexity
The only reason cnt is necessary is that k is divisible by 1 and k. If you change
for (int i=1; i<=k; i++) { // 'i' is the number 'k' is divided by
to
for (int i=2; i<k; ++i) { // 'i' is the number 'k' is divided by
then both of those cases are eliminated, and the loop can exit as soon as it finds a value of i for which k%i == 0.
2: Efficiency
The test
for (int i=2; i<k; ++i) { // 'i' is the number 'k' is divided by
is still quite inefficient for two reasons. First, there's no need to test every even number; if k > 2 and (k % 2) == 0, then k cannot be prime. So you can eliminate half of the tests by checking explicitly for 2 (prime) or divisibility by 2 (not prime), and then using
for (int i = 3; i < k; i += 2) { // 'i' is the number 'k' is divided by
But you can make this still more efficient, because you can stop after reaching sqrt(k). Why? If k is divisible by some number i, then it must also be divisible by k/i (because i * k/i=k). And if i > sqrt(k), then k/i < sqrt(k) and the loop would already have exited. So you need only
int r = (int) sqrt(k);
for (int i = 3; i <= r; i += 2) { // 'i' is the number 'k' is divided by
If sqrt() isn't available, you can use
for (int i = 3; i*i <= k; i += 2) { // 'i' is the number 'k' is divided by
3: Style
Just a simple thing, but instead of
int n = 0;
n=20;
you can simply write
int n = 20;
Your primesArr variable is uninitialized.
Declaring a pointer as
int *ptr;
Just declares a pointer to an int. However, the pointer itself does not point to anything. Much like declaring
int val;
does not initialize val. Therefore, you'll need to allocate memory for your primesArr pointer to point to (with new or on the stack like int primesArr[N] where N is some large number.
However, since you don't know how many primes you'll get a priori from your genPrimes function and you haven't said that STL is out of the question, I'd consider using a std::vector<int> as the input to your genPrimes function:
int genPrimes(int seed, std::vector<int>& test)
And, from within the function, you could do:
test.push_back(k)
Related
Given a number n
Find the count of the sub numbers of size x in a number num which divides num.
For example, if the number is 250
and x=2
the answer will be 2
as 250%25==0
and 250 % 50==0.
Can anyone help me out with the cpp code ?
class Solution {
public:
int divisorSubstrings(int num, int k) {
string s=to_string(num);
int count=0;
int i=0;
int j=k-1;
string temp="";
for(int k=i;k<=j;k++)
{
temp.push_back(s[k]);
}
while(j<s.length())
{
if(num%stoi(temp)==0)
count++;
temp.erase(temp.begin() + i-1);
j++;
i++;
temp.push_back(s[j]);
}
return count;
}
};
this is showing runtime error
You have a number of problems. First, using simple letters for your variables means we don't have a clue what those variables are for. Use meaningful names.
Second, this:
for(int k=i;k<=j;k++)
You have an argument to your method called k. You've now shadowed it. Technically, you can do that, but it's a really really bad habit.
But the real problem is here:
temp.erase(temp.begin() + i-1);
i is initialize to 0 and never changed until AFTER this line runs the first time. So you're actually erasing a character before the start of the string.
I am working on producing C++ code to list all primes between 1 and 100 say. In order to present my question I need to provide some background.
The basic idea of what I want to do is the following:
Introduce a vector to hold all the primes in ascending order. If the first j elements of this vector are given, the j+1 element is then given as the smallest integer larger than the j'th element which is not divisible by any of the first j elements. The first element is moreover given to be 2.
Thus if v denotes the vector of primes, I want to produce code which implements the following math-type argument;
v[1]=2;
for(2<i<=100)
if i % v[j] !=0 FOR ALL 0<j< v.size()
v.push_back(i)
else
do nothing
The problem I am facing however is that C++ doesn't seem to have a for all type language construct. In order to get around this I introduced a counter variable. More precisely:
int main() {
const int max=100;
vector<int>primes; // vector holding list of primes up to some number.
for(int i=2; i<=max;++i){
if(i==2)
primes.push_back(i); // inserts 2 as first prime
else{
double counter=primes.size(); // counter to be used in following loop.
for(int j=0;j<primes.size();++j){
if(i% primes[j]==0){
break; // breaks loop if prime divisor found!
}
else{
counter-=1; //counter starts at the current size of the primes vector, and 1 is deducted each time an entry is not a prime divisor.
}
}
if (counter==0) // if the counter reaches 0 then i has no prime divisors so must be prime.
primes.push_back(i);
}
}
for(int i=0; i<primes.size(); ++i){
cout << primes[i] << '\t';
}
return 0;
}
The questions I would like to ask are then as follows:
Is there a for-all type language construct in C++?
If not, is there a more appropriate way to implement the above idea? In particular is my use of the counter variable frowned upon?
(Bonus) Is anyone aware of a more efficient way to find all the primes? The above works relatively well up to 1,,000,000 but poorly up to 1 billion.
Note I am beginner to C++ and coding in general (currently working through the book of Stroustrup) so answers provided with that in mind would be appreciated.
Thanks in advance!
EDIT:
Hello all,
Thank you for your comments. From them I learned that both use of a counter and a for all type statement are unnecessary. Instead one can assign a true or false value to each integer indicating whether a number is prime with only integers having a true value added to the vector. Setting things up in this way also allows the process of checking whether a number is prime given the currently known'' primes to be independent of the process of updating the currently known'' primes. This consequently addresses another criticism of my code which was that it was trying to do too many things at once.
Finally it was pointed out to me that there are some basic ways of improving the efficiency of the prime divisor algorithm for finding primes by, for instance, discounting all even numbers greater than 2 in the search (implemented by starting the appropriate loop at 3 and then increasing by 2 at each stage). More generally it was noted that algorithms such as the sieve of Erastothenes are much faster for finding primes, as these are based on multiplication not division. Here is the final code:
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
vector<int> primes; // vector holding list of primes up to some number.
bool is_prime(int n) {// Given integer n and a vector of primes this boolean valued function returns false if any of the primes is a prime divisor of n, and true otherwise. In the context of the main function, the list of primes will be all those that precede n, hence a return of a true value means that n is itself prime. Hence the function name.
for (int p = 0; p < primes.size(); ++p)
if (n % primes[p] == 0) {
return false;
break; // Breaks loop as soon as the first prime divisor is found.
}
return true;
}
int main() {
const int max=100;
primes.push_back(2);
for (int i = 3; i <= max; i+=2)
if (is_prime(i) == true) primes.push_back(i);
for(int i=0; i<primes.size(); ++i)
cout << primes[i] << '\t';
return 0;
}
I just have one additional question: I checked how long the algorithm takes up to 1,000,000 and the presence of the break in the is_prime function (which stops the search for a prime divisor as soon as one is found) doesn't seem to have an effect on the time. Why is this so?
thanks for all the help!
my program seems correct but I don't know why it has a logic problem
int main()
{
int r,s=0;
for(int i=10000;i<=998001;i++)
{
while (i>0)
{
r=i%10;
s=s*10+r;
i=i/10;
}
cout<<s<<endl;
}
Your question and code don't seem to match Ali. You have told that you need the largest possible palindrome, but you are printing each and every reversed number. And your code has glitches too. I will list the mistakes and corresponding changes to be made:
using i as both the for loop counter variable and as well as the number you're reversing. This causes i to become 0 after every reversal and hence the for loop never ends. The fix for this... use another variable, say num, and equate it to i at the start of the loop. This ensures that i remains unchanged and for goes unfazed.
use long int instead of int. This avoids any anomalies and chances of junk numbers.
s(the sum variable) is initialized only at the start. Hence every time you calculate a new reversed number, it is adding s to its previous value. The fix: Initialize s to 0 at the start of for loop so that you get a fresh reversed for every i value.
You are not checking for any palindrome condition. You are just printing the reversed number. The fix: Hence check if the the number is a palindrome, i.e, if the number ,i.e., i is equal to the reversed number, i.e., s
I have attached the code below. I am currently printing the greatest palindrome in the range in which you were checking. In case you need all the palindromes, just uncomment the commented cout line.
CODE:
#include <iostream>
using namespace std;
int main()
{
int r, s = 0;
long int num, max = 0;
for(long int i = 10000; i <= 998001; i++)
{
s = 0;
num = i;
while (num > 0)
{
r = num % 10;
s = s * 10 + r;
num = num / 10;
}
if(s == i) {
//cout<<s<<endl; //uncomment this line if you intend to display all palindromes
if(i > max)
max = i;
}
}
cout<<max<<endl;
}
My algorithm runs correctly up to the first 100 primes but then something goes wrong. Please have a look at my code below, I tried to follow the pseudo-code given here https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main()
{
int n = 1000; //compute primes up to this number
vector<bool> p(true,n); //all values set to true, from 0 to n
for(int i = 2; i < sqrt(n)+1; i++){
if( p[i-1] == true ){
for(int j = i*i; j < n; j += i) //start looking for multiples of prime i at i*i (optimized)
p[j-1] = false;
}
}
for(int i = 2; i < n; i++){
if( p[i-1] == true )
cout << i << "\n";
}
return 0;
}
The output is:
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
193
199
I'm absolutely amazed the program runs at all. It has an absolute truckload of undefined behaviour!.
Unless I'm very much mistaken (in which case please reward the serenity of my Friday afternoon with downvotes), vector<bool> p(true, n) is creating a vector of size true, with the elements initialised to n.
You have the constructor arguments the wrong way round. This is effectively reversing the sieve for most of the values.
Have you absolutely clobbered your compiler's warning level?
First of all, you do not need to store a boolean value for each and every number. This way, you are wasting memory. You should store only the found primes instead, unless you have a very good reason not to do so.
I will not implement the code, since it would spoil the joy of learning. You should implement the following:
Initialize p as a vector of integers.
Store 2 as first value inside p
Iterate all odd numbers starting from 3 and ending at the end number
For each number, calculate its square root and store it into a variable
Iterate all previous elements of the p until you reach a divisor or the value of the vector at the given index reaches the square root, starting from the second element, as pair numbers larger than 2 are ignored
If you find a divisor inside your inner loop, store it into your vector and get out of the inner loop
At the end you will have a vector of primes, indexes will mean the prime index and the values will be actual primes. Each element will be a prime of its own.
Your vector construction is wrong. It must be
vector<bool> p(n, true); //all values set to true, from 0 to n
instead of
vector<bool> p(true, n); //all values set to true, from 0 to n
You mess your numbering up. If p[k] is the primeness of number k+1, your for loop is wrong
for(int j = i*i; j < n; j += i)
and should be
for(int j = (i-1)*(i-1); j < n; j += (i-1))
My advice would be to use more informative variable names and avoid those sources of confusion like p[k] giving information about integer k+1.
So I need help with my code. For some reason it keeps crashing when I enter a number past 500,000. Here is the exact assignment.
Implement the Sieve of Eratosthenes and use it to find all prime
numbers less than or equal to one million. Use the result to
prove Goldbach's Conjecture for all even integers between four and
one million, inclusive.
Implement a function with the following declaration:
void sieve(int array[], int num);
This function takes an integer array as its argument. The array
should be initialized to the values 1 through 1000000. The
function modifies the array so that only the prime numbers remain;
all other values are zeroed out.
This function must be written to accept an integer array of any
size. You must should output for all primes numbers between 1 and
1000000, but when I test your function it may be on an array of a
different size.
Implement a function with the following declaration:
void goldbach(int array[], int num);
This function takes the same argument as the previous function
and displays each even integer between 4 and 1000000 with two
prime numbers that add to it.
The goal here is to provide an efficient implementation. This
means no multiplication, division, or modulus when determining if
a number is prime. It also means that the second function must find
two primes efficiently.
Output for your program:
All prime numbers between 1 and 1000000
and all even numbers between 4 and 1000000 and the two prime
numbers that sum up to it.
DO NOT provide output or a session record for this project!
And here is what I have so far. If anyone could help me that would be great.
#include <iostream>
using namespace std;
void sieve (int array[], int num);
int main()
{
int num;
cout << "Enter a number to calculate up to." << endl;
cin>> num;
if ( num < 2 )
return 0;
int array[num];
array[0]= array[1]= 0;
for ( int i= 2; i < num; ++i )
array[i]= i;
sieve(array,num);
for (int i=0; i<num; i++)
if (array[i] > 0)
cout << array[i] <<" "<<endl;
cout<<endl;
return 0;
}
void sieve( int array[], int num )
{
for ( int i= 0; i < num; ++i )
{
if ( array[i] != 0 )
{
for ( int j= i+i; j < num; j += i )
{
array[j]= 0;
}
}
}
}
The reason why your code crashes is that you're using VLA allocation for the array here
int array[num];
It's used to allocate num int elements of the stack, which is most probably too small to hold a million of int values.
You should note it's not a standard c++ feature, but an extension provided by a number of compiler implementations.
To fix this there are three alternatives:
You configure the stack size used for your program to be big enough to hold the number of int elements (this is OS dependend)
You use a std::vector<int> array(num); instead, that allocates these elements on the heap memory
You allocate the necessary memory on the heap yourself using int* array = new int[num]; and delete [] array; at the end of your program (I wouldn't recommend this solution, because it's prone to make silly mistakes regarding the proper memory management)
As I see this is an assignment, you need to write your own code, but I have a few ideas to reduce the amount of memory significantly.
Why don't you use array of bits instead ?
Do something like
#define IS_SET(x) (arr[(x)>>3] & (0x01 << ((x) & 0x07)))
#define SET(x) (arr[(x)>>3] |= (0x01 << ((x) & 0x07)))
and define arr as an array of char. This will make the memory utilization 8 folds down. For C++ you can use bool might not get you the lowest possible memory usage.
First clear out all the char elements. Then for each number set bits using SET(x) an once all marking is done. If IS_SET(x) evaluates false then x is prime.
Saves large amount of memory.
EDIT1:
Another trick to cut 50% of the memory required is not to retain space for the even numbers. Start with i=3 and always increment using i+=2 and mark the bit arrays. While reading do the same.
EDIT2:
If you can find a series which skips the integers which are multiple of two or three or both, then you can save around 30% more memory. In fact you can make such a series and skip storing and marking for the multiples of two and three or both.