Sieve of eratosthenes with std::vector
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
4
down vote
favorite
How can I improve and optimise this code?
#include <iostream>
#include <vector>
std::vector<bool> sieve_of_eratosthenes(int n)
std::vector<bool> primes(n+1, true);
primes[0] = false;
primes[1] = false;
for (int i = 2; i <= n; i++)
if (primes[i] == true)
for (int j = i * 2; j <= n; j += i)
primes[j] = false;
return primes;
int main()
int n;
std::cout << "Enter number :n";
std::cin >> n;
std::vector<bool> result = sieve_of_eratosthenes(n);
std::cout << "Prime numbers upto " << n << " is :n";
for (int i = 0 ; i < result.size(); i++)
if (result[i] == true)
std::cout << i << " ";
std::cout << 'n';
c++ console sieve-of-eratosthenes
add a comment |Â
up vote
4
down vote
favorite
How can I improve and optimise this code?
#include <iostream>
#include <vector>
std::vector<bool> sieve_of_eratosthenes(int n)
std::vector<bool> primes(n+1, true);
primes[0] = false;
primes[1] = false;
for (int i = 2; i <= n; i++)
if (primes[i] == true)
for (int j = i * 2; j <= n; j += i)
primes[j] = false;
return primes;
int main()
int n;
std::cout << "Enter number :n";
std::cin >> n;
std::vector<bool> result = sieve_of_eratosthenes(n);
std::cout << "Prime numbers upto " << n << " is :n";
for (int i = 0 ; i < result.size(); i++)
if (result[i] == true)
std::cout << i << " ";
std::cout << 'n';
c++ console sieve-of-eratosthenes
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
How can I improve and optimise this code?
#include <iostream>
#include <vector>
std::vector<bool> sieve_of_eratosthenes(int n)
std::vector<bool> primes(n+1, true);
primes[0] = false;
primes[1] = false;
for (int i = 2; i <= n; i++)
if (primes[i] == true)
for (int j = i * 2; j <= n; j += i)
primes[j] = false;
return primes;
int main()
int n;
std::cout << "Enter number :n";
std::cin >> n;
std::vector<bool> result = sieve_of_eratosthenes(n);
std::cout << "Prime numbers upto " << n << " is :n";
for (int i = 0 ; i < result.size(); i++)
if (result[i] == true)
std::cout << i << " ";
std::cout << 'n';
c++ console sieve-of-eratosthenes
How can I improve and optimise this code?
#include <iostream>
#include <vector>
std::vector<bool> sieve_of_eratosthenes(int n)
std::vector<bool> primes(n+1, true);
primes[0] = false;
primes[1] = false;
for (int i = 2; i <= n; i++)
if (primes[i] == true)
for (int j = i * 2; j <= n; j += i)
primes[j] = false;
return primes;
int main()
int n;
std::cout << "Enter number :n";
std::cin >> n;
std::vector<bool> result = sieve_of_eratosthenes(n);
std::cout << "Prime numbers upto " << n << " is :n";
for (int i = 0 ; i < result.size(); i++)
if (result[i] == true)
std::cout << i << " ";
std::cout << 'n';
c++ console sieve-of-eratosthenes
edited Apr 15 at 6:12
Deduplicator
9,8601844
9,8601844
asked Apr 14 at 8:34
coder
911425
911425
add a comment |Â
add a comment |Â
4 Answers
4
active
oldest
votes
up vote
2
down vote
accepted
I see a few things that may help you improve your program.
Be careful with signed versus unsigned
If a negative number is passed to the sieve_of_eratosthenes
function, it's unlikely to produce useful results. For that reason, it would make sense to reject negative numbers when getting the value from the user and/or declare the function to accept only unsigned
.
Consider the user
Rather than require an interactive session, it would be convenient to specify the number on the command line. Also, grammatically, it seems to me that it should say "Prime numbers up to n are:"
Reduce iterations
Other than 2, only odd numbers are possible primes. For that reason, I'd suggest changing the initialization to this:
std::vector<bool> primes(n+1);
primes[2] = true;
// all odd numbers are possible primes
for (unsigned i = 3; i <= n; i+=2)
primes[i] = true;
Note that primes(n+1)
will initialize the entire vector to false
, inverting the initialization of the original code.
One need only iterate up to $sqrtn$ for the outer loop. Some thinking about that should reveal why this is so.
In a similar vein, we can start the inner loop with the value of i * i
because any smaller multiple will already have been crossed out.
Test alternative representations for performance
It's frequently asserted that some other representation, such as std::vector<std::byte>
or std::vector<char>
will be faster than std::vector<bool>
. Intuitively this makes some sense because std::vector<bool>
has to do packing and unpacking of bits to access. However, this intuition isn't always correct because of cache effects. That is, it's often faster to do complex manipulations in cache than it is to do simple operations on memory areas not in the cache. We can guess at this, but the better method is to test it on your machine with your compiler. To simplify such testing, I used this code:
#include <iostream>
#include <vector>
#include <cmath>
#if 0
#include <cstddef>
using mytype = std::byte;
#else
using mytype = bool;
#endif
constexpr mytype yes1;
constexpr mytype no0;
std::vector<mytype> sieve_of_eratosthenes(unsigned n)
std::vector<mytype> primes(n+1);
primes[2] = yes;
// all odd numbers are possible primes
for (unsigned i = 3; i <= n; i+=2)
primes[i] = yes;
// we only have to check up to the square root of the limit
unsigned limit = std::sqrt(n);
for (unsigned i = 3; i <= limit; i+=2)
if (primes[i] == yes)
const unsigned stride2 * i;
for (unsigned j = i * i; j <= n; j += stride)
primes[j] = no;
return primes;
int main(int argc, char *argv)
if (argc != 2)
std::cout << "Usage: primesUpTo nn";
return 1;
int natoi(argv[1]);
if (n < 0)
std::cout << "Error: the number must be positiven";
return 2;
std::vector<mytype> result = sieve_of_eratosthenes(n);
std::cout << "Prime numbers up to " << n << " are:n";
for (unsigned i = 0 ; i < result.size(); i++)
if (result[i] == yes)
std::cout << i << 'n';
std::cout << 'n';
Using a bash
script using time
and R
on my machine (a 64-bit Linux box, using gcc version 7.3.1) I get the following results, but remember that your results may differ and so I'd strongly encourage you to do your own testing. In each of the graphs, the red line is the version using std::byte
and the green line is the version using std::bool
. As you can see, in my testing std::bool
almost always wins in both execution speed and memory size.
add a comment |Â
up vote
5
down vote
Aside from the other optimizations, if you are using the sieve to check for primality of a number, you can optimize further, every prime after 2 is odd, therefore any even number that isn't 2 is not prime. This can easily be checked without the sieve. I would suggest that marking all the even numbers false is superfluous. So mark 2 as true and start the outer loop at 3 and increment by 2. As was mentioned, the inner loop can start at i*i
, and since this will be an odd number you only need to mark every other multiple, therefore you can increment by i*2
. Something like this:
std::vector<bool> sieve_of_eratosthenes(int n)
std::vector<bool> primes(n+1, true);
primes[0] = false;
primes[1] = false;
int limit = (int)sqrt(n) + 1;
for (int i = 3; i < limit; i += 2)
if (primes[i])
int step = i * 2;
for (int j = i * i; j <= n; j += step)
primes[j] = false;
return primes;
This will not produce correct answers because it incorrectly indicates all even numbers are prime.
â Edward
Apr 15 at 11:27
Like my answer says, check even numbers without the sieve. Use it for only odd numbers..
â tinstaafl
Apr 15 at 11:29
But that leaves all of the even numbers (except 2) in the vector set incorrectly.
â Edward
Apr 15 at 11:30
Yes but none of the even numbers are used, only the odd ones.
â tinstaafl
Apr 15 at 11:32
add a comment |Â
up vote
3
down vote
With your j
loop in sieve_of_eratosthenes
you can start at i * i
, since all the multiples of i
with factors less than i
will have already been removed. And you can stop the i
loop when i * i > n
(a condition you can check when you find a new prime, before the j
loop).
add a comment |Â
up vote
3
down vote
DonâÂÂt use the weird vector<bool>
. Using a vector of bytes will be faster, and using a bitset will give you the compactness if that was your intent.
Writing if (x==true)
is silly.
Use uniform initialization:
std::vector<std::byte> primes n+1, true ;
edit: (vector
has an init-list constructor in addition to other constructors. Touted as a feature when uniform init was promoted, it actually causes headscratching in code reviews exactly as I just fell into myself!)
use auto
(almost everywhere):
auto result= sieve(n);
I have doubts that astd::bitset
would be a sufficient data structure to implement a reasonably sized sieve of eratosthenes. Anyways, I'd agree going with thestd::vector<std::byte>
.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:07
@ÃÂìýÃÂÃ񠨝õῠstd::bitset can be of any length. It maintains an array of native-sized words, though PlaugerâÂÂs does seem to have optimization for small values of N.
â JDà Âugosz
Apr 14 at 10:46
May be you misunderstood me. Astd::bitset
can be build on top of a maxlong long
value. Astd::vector<std::bitset<64>>
might help to improve over astd::vector<bool>
while keeping the compactness in memory, you have to adapt your index calculations though.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:50
2
I'd advocate measuring rather than guessing when it comes to performance questions.
â Edward
Apr 14 at 15:16
1
@Edward, IIRC it will cause compilation error, as the second element requires conversion. I tried to compile it, but the error is too cryptic to understand :)
â Incomputable
Apr 14 at 16:34
 |Â
show 4 more comments
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
I see a few things that may help you improve your program.
Be careful with signed versus unsigned
If a negative number is passed to the sieve_of_eratosthenes
function, it's unlikely to produce useful results. For that reason, it would make sense to reject negative numbers when getting the value from the user and/or declare the function to accept only unsigned
.
Consider the user
Rather than require an interactive session, it would be convenient to specify the number on the command line. Also, grammatically, it seems to me that it should say "Prime numbers up to n are:"
Reduce iterations
Other than 2, only odd numbers are possible primes. For that reason, I'd suggest changing the initialization to this:
std::vector<bool> primes(n+1);
primes[2] = true;
// all odd numbers are possible primes
for (unsigned i = 3; i <= n; i+=2)
primes[i] = true;
Note that primes(n+1)
will initialize the entire vector to false
, inverting the initialization of the original code.
One need only iterate up to $sqrtn$ for the outer loop. Some thinking about that should reveal why this is so.
In a similar vein, we can start the inner loop with the value of i * i
because any smaller multiple will already have been crossed out.
Test alternative representations for performance
It's frequently asserted that some other representation, such as std::vector<std::byte>
or std::vector<char>
will be faster than std::vector<bool>
. Intuitively this makes some sense because std::vector<bool>
has to do packing and unpacking of bits to access. However, this intuition isn't always correct because of cache effects. That is, it's often faster to do complex manipulations in cache than it is to do simple operations on memory areas not in the cache. We can guess at this, but the better method is to test it on your machine with your compiler. To simplify such testing, I used this code:
#include <iostream>
#include <vector>
#include <cmath>
#if 0
#include <cstddef>
using mytype = std::byte;
#else
using mytype = bool;
#endif
constexpr mytype yes1;
constexpr mytype no0;
std::vector<mytype> sieve_of_eratosthenes(unsigned n)
std::vector<mytype> primes(n+1);
primes[2] = yes;
// all odd numbers are possible primes
for (unsigned i = 3; i <= n; i+=2)
primes[i] = yes;
// we only have to check up to the square root of the limit
unsigned limit = std::sqrt(n);
for (unsigned i = 3; i <= limit; i+=2)
if (primes[i] == yes)
const unsigned stride2 * i;
for (unsigned j = i * i; j <= n; j += stride)
primes[j] = no;
return primes;
int main(int argc, char *argv)
if (argc != 2)
std::cout << "Usage: primesUpTo nn";
return 1;
int natoi(argv[1]);
if (n < 0)
std::cout << "Error: the number must be positiven";
return 2;
std::vector<mytype> result = sieve_of_eratosthenes(n);
std::cout << "Prime numbers up to " << n << " are:n";
for (unsigned i = 0 ; i < result.size(); i++)
if (result[i] == yes)
std::cout << i << 'n';
std::cout << 'n';
Using a bash
script using time
and R
on my machine (a 64-bit Linux box, using gcc version 7.3.1) I get the following results, but remember that your results may differ and so I'd strongly encourage you to do your own testing. In each of the graphs, the red line is the version using std::byte
and the green line is the version using std::bool
. As you can see, in my testing std::bool
almost always wins in both execution speed and memory size.
add a comment |Â
up vote
2
down vote
accepted
I see a few things that may help you improve your program.
Be careful with signed versus unsigned
If a negative number is passed to the sieve_of_eratosthenes
function, it's unlikely to produce useful results. For that reason, it would make sense to reject negative numbers when getting the value from the user and/or declare the function to accept only unsigned
.
Consider the user
Rather than require an interactive session, it would be convenient to specify the number on the command line. Also, grammatically, it seems to me that it should say "Prime numbers up to n are:"
Reduce iterations
Other than 2, only odd numbers are possible primes. For that reason, I'd suggest changing the initialization to this:
std::vector<bool> primes(n+1);
primes[2] = true;
// all odd numbers are possible primes
for (unsigned i = 3; i <= n; i+=2)
primes[i] = true;
Note that primes(n+1)
will initialize the entire vector to false
, inverting the initialization of the original code.
One need only iterate up to $sqrtn$ for the outer loop. Some thinking about that should reveal why this is so.
In a similar vein, we can start the inner loop with the value of i * i
because any smaller multiple will already have been crossed out.
Test alternative representations for performance
It's frequently asserted that some other representation, such as std::vector<std::byte>
or std::vector<char>
will be faster than std::vector<bool>
. Intuitively this makes some sense because std::vector<bool>
has to do packing and unpacking of bits to access. However, this intuition isn't always correct because of cache effects. That is, it's often faster to do complex manipulations in cache than it is to do simple operations on memory areas not in the cache. We can guess at this, but the better method is to test it on your machine with your compiler. To simplify such testing, I used this code:
#include <iostream>
#include <vector>
#include <cmath>
#if 0
#include <cstddef>
using mytype = std::byte;
#else
using mytype = bool;
#endif
constexpr mytype yes1;
constexpr mytype no0;
std::vector<mytype> sieve_of_eratosthenes(unsigned n)
std::vector<mytype> primes(n+1);
primes[2] = yes;
// all odd numbers are possible primes
for (unsigned i = 3; i <= n; i+=2)
primes[i] = yes;
// we only have to check up to the square root of the limit
unsigned limit = std::sqrt(n);
for (unsigned i = 3; i <= limit; i+=2)
if (primes[i] == yes)
const unsigned stride2 * i;
for (unsigned j = i * i; j <= n; j += stride)
primes[j] = no;
return primes;
int main(int argc, char *argv)
if (argc != 2)
std::cout << "Usage: primesUpTo nn";
return 1;
int natoi(argv[1]);
if (n < 0)
std::cout << "Error: the number must be positiven";
return 2;
std::vector<mytype> result = sieve_of_eratosthenes(n);
std::cout << "Prime numbers up to " << n << " are:n";
for (unsigned i = 0 ; i < result.size(); i++)
if (result[i] == yes)
std::cout << i << 'n';
std::cout << 'n';
Using a bash
script using time
and R
on my machine (a 64-bit Linux box, using gcc version 7.3.1) I get the following results, but remember that your results may differ and so I'd strongly encourage you to do your own testing. In each of the graphs, the red line is the version using std::byte
and the green line is the version using std::bool
. As you can see, in my testing std::bool
almost always wins in both execution speed and memory size.
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
I see a few things that may help you improve your program.
Be careful with signed versus unsigned
If a negative number is passed to the sieve_of_eratosthenes
function, it's unlikely to produce useful results. For that reason, it would make sense to reject negative numbers when getting the value from the user and/or declare the function to accept only unsigned
.
Consider the user
Rather than require an interactive session, it would be convenient to specify the number on the command line. Also, grammatically, it seems to me that it should say "Prime numbers up to n are:"
Reduce iterations
Other than 2, only odd numbers are possible primes. For that reason, I'd suggest changing the initialization to this:
std::vector<bool> primes(n+1);
primes[2] = true;
// all odd numbers are possible primes
for (unsigned i = 3; i <= n; i+=2)
primes[i] = true;
Note that primes(n+1)
will initialize the entire vector to false
, inverting the initialization of the original code.
One need only iterate up to $sqrtn$ for the outer loop. Some thinking about that should reveal why this is so.
In a similar vein, we can start the inner loop with the value of i * i
because any smaller multiple will already have been crossed out.
Test alternative representations for performance
It's frequently asserted that some other representation, such as std::vector<std::byte>
or std::vector<char>
will be faster than std::vector<bool>
. Intuitively this makes some sense because std::vector<bool>
has to do packing and unpacking of bits to access. However, this intuition isn't always correct because of cache effects. That is, it's often faster to do complex manipulations in cache than it is to do simple operations on memory areas not in the cache. We can guess at this, but the better method is to test it on your machine with your compiler. To simplify such testing, I used this code:
#include <iostream>
#include <vector>
#include <cmath>
#if 0
#include <cstddef>
using mytype = std::byte;
#else
using mytype = bool;
#endif
constexpr mytype yes1;
constexpr mytype no0;
std::vector<mytype> sieve_of_eratosthenes(unsigned n)
std::vector<mytype> primes(n+1);
primes[2] = yes;
// all odd numbers are possible primes
for (unsigned i = 3; i <= n; i+=2)
primes[i] = yes;
// we only have to check up to the square root of the limit
unsigned limit = std::sqrt(n);
for (unsigned i = 3; i <= limit; i+=2)
if (primes[i] == yes)
const unsigned stride2 * i;
for (unsigned j = i * i; j <= n; j += stride)
primes[j] = no;
return primes;
int main(int argc, char *argv)
if (argc != 2)
std::cout << "Usage: primesUpTo nn";
return 1;
int natoi(argv[1]);
if (n < 0)
std::cout << "Error: the number must be positiven";
return 2;
std::vector<mytype> result = sieve_of_eratosthenes(n);
std::cout << "Prime numbers up to " << n << " are:n";
for (unsigned i = 0 ; i < result.size(); i++)
if (result[i] == yes)
std::cout << i << 'n';
std::cout << 'n';
Using a bash
script using time
and R
on my machine (a 64-bit Linux box, using gcc version 7.3.1) I get the following results, but remember that your results may differ and so I'd strongly encourage you to do your own testing. In each of the graphs, the red line is the version using std::byte
and the green line is the version using std::bool
. As you can see, in my testing std::bool
almost always wins in both execution speed and memory size.
I see a few things that may help you improve your program.
Be careful with signed versus unsigned
If a negative number is passed to the sieve_of_eratosthenes
function, it's unlikely to produce useful results. For that reason, it would make sense to reject negative numbers when getting the value from the user and/or declare the function to accept only unsigned
.
Consider the user
Rather than require an interactive session, it would be convenient to specify the number on the command line. Also, grammatically, it seems to me that it should say "Prime numbers up to n are:"
Reduce iterations
Other than 2, only odd numbers are possible primes. For that reason, I'd suggest changing the initialization to this:
std::vector<bool> primes(n+1);
primes[2] = true;
// all odd numbers are possible primes
for (unsigned i = 3; i <= n; i+=2)
primes[i] = true;
Note that primes(n+1)
will initialize the entire vector to false
, inverting the initialization of the original code.
One need only iterate up to $sqrtn$ for the outer loop. Some thinking about that should reveal why this is so.
In a similar vein, we can start the inner loop with the value of i * i
because any smaller multiple will already have been crossed out.
Test alternative representations for performance
It's frequently asserted that some other representation, such as std::vector<std::byte>
or std::vector<char>
will be faster than std::vector<bool>
. Intuitively this makes some sense because std::vector<bool>
has to do packing and unpacking of bits to access. However, this intuition isn't always correct because of cache effects. That is, it's often faster to do complex manipulations in cache than it is to do simple operations on memory areas not in the cache. We can guess at this, but the better method is to test it on your machine with your compiler. To simplify such testing, I used this code:
#include <iostream>
#include <vector>
#include <cmath>
#if 0
#include <cstddef>
using mytype = std::byte;
#else
using mytype = bool;
#endif
constexpr mytype yes1;
constexpr mytype no0;
std::vector<mytype> sieve_of_eratosthenes(unsigned n)
std::vector<mytype> primes(n+1);
primes[2] = yes;
// all odd numbers are possible primes
for (unsigned i = 3; i <= n; i+=2)
primes[i] = yes;
// we only have to check up to the square root of the limit
unsigned limit = std::sqrt(n);
for (unsigned i = 3; i <= limit; i+=2)
if (primes[i] == yes)
const unsigned stride2 * i;
for (unsigned j = i * i; j <= n; j += stride)
primes[j] = no;
return primes;
int main(int argc, char *argv)
if (argc != 2)
std::cout << "Usage: primesUpTo nn";
return 1;
int natoi(argv[1]);
if (n < 0)
std::cout << "Error: the number must be positiven";
return 2;
std::vector<mytype> result = sieve_of_eratosthenes(n);
std::cout << "Prime numbers up to " << n << " are:n";
for (unsigned i = 0 ; i < result.size(); i++)
if (result[i] == yes)
std::cout << i << 'n';
std::cout << 'n';
Using a bash
script using time
and R
on my machine (a 64-bit Linux box, using gcc version 7.3.1) I get the following results, but remember that your results may differ and so I'd strongly encourage you to do your own testing. In each of the graphs, the red line is the version using std::byte
and the green line is the version using std::bool
. As you can see, in my testing std::bool
almost always wins in both execution speed and memory size.
edited Apr 15 at 15:33
answered Apr 15 at 14:00
Edward
44k374201
44k374201
add a comment |Â
add a comment |Â
up vote
5
down vote
Aside from the other optimizations, if you are using the sieve to check for primality of a number, you can optimize further, every prime after 2 is odd, therefore any even number that isn't 2 is not prime. This can easily be checked without the sieve. I would suggest that marking all the even numbers false is superfluous. So mark 2 as true and start the outer loop at 3 and increment by 2. As was mentioned, the inner loop can start at i*i
, and since this will be an odd number you only need to mark every other multiple, therefore you can increment by i*2
. Something like this:
std::vector<bool> sieve_of_eratosthenes(int n)
std::vector<bool> primes(n+1, true);
primes[0] = false;
primes[1] = false;
int limit = (int)sqrt(n) + 1;
for (int i = 3; i < limit; i += 2)
if (primes[i])
int step = i * 2;
for (int j = i * i; j <= n; j += step)
primes[j] = false;
return primes;
This will not produce correct answers because it incorrectly indicates all even numbers are prime.
â Edward
Apr 15 at 11:27
Like my answer says, check even numbers without the sieve. Use it for only odd numbers..
â tinstaafl
Apr 15 at 11:29
But that leaves all of the even numbers (except 2) in the vector set incorrectly.
â Edward
Apr 15 at 11:30
Yes but none of the even numbers are used, only the odd ones.
â tinstaafl
Apr 15 at 11:32
add a comment |Â
up vote
5
down vote
Aside from the other optimizations, if you are using the sieve to check for primality of a number, you can optimize further, every prime after 2 is odd, therefore any even number that isn't 2 is not prime. This can easily be checked without the sieve. I would suggest that marking all the even numbers false is superfluous. So mark 2 as true and start the outer loop at 3 and increment by 2. As was mentioned, the inner loop can start at i*i
, and since this will be an odd number you only need to mark every other multiple, therefore you can increment by i*2
. Something like this:
std::vector<bool> sieve_of_eratosthenes(int n)
std::vector<bool> primes(n+1, true);
primes[0] = false;
primes[1] = false;
int limit = (int)sqrt(n) + 1;
for (int i = 3; i < limit; i += 2)
if (primes[i])
int step = i * 2;
for (int j = i * i; j <= n; j += step)
primes[j] = false;
return primes;
This will not produce correct answers because it incorrectly indicates all even numbers are prime.
â Edward
Apr 15 at 11:27
Like my answer says, check even numbers without the sieve. Use it for only odd numbers..
â tinstaafl
Apr 15 at 11:29
But that leaves all of the even numbers (except 2) in the vector set incorrectly.
â Edward
Apr 15 at 11:30
Yes but none of the even numbers are used, only the odd ones.
â tinstaafl
Apr 15 at 11:32
add a comment |Â
up vote
5
down vote
up vote
5
down vote
Aside from the other optimizations, if you are using the sieve to check for primality of a number, you can optimize further, every prime after 2 is odd, therefore any even number that isn't 2 is not prime. This can easily be checked without the sieve. I would suggest that marking all the even numbers false is superfluous. So mark 2 as true and start the outer loop at 3 and increment by 2. As was mentioned, the inner loop can start at i*i
, and since this will be an odd number you only need to mark every other multiple, therefore you can increment by i*2
. Something like this:
std::vector<bool> sieve_of_eratosthenes(int n)
std::vector<bool> primes(n+1, true);
primes[0] = false;
primes[1] = false;
int limit = (int)sqrt(n) + 1;
for (int i = 3; i < limit; i += 2)
if (primes[i])
int step = i * 2;
for (int j = i * i; j <= n; j += step)
primes[j] = false;
return primes;
Aside from the other optimizations, if you are using the sieve to check for primality of a number, you can optimize further, every prime after 2 is odd, therefore any even number that isn't 2 is not prime. This can easily be checked without the sieve. I would suggest that marking all the even numbers false is superfluous. So mark 2 as true and start the outer loop at 3 and increment by 2. As was mentioned, the inner loop can start at i*i
, and since this will be an odd number you only need to mark every other multiple, therefore you can increment by i*2
. Something like this:
std::vector<bool> sieve_of_eratosthenes(int n)
std::vector<bool> primes(n+1, true);
primes[0] = false;
primes[1] = false;
int limit = (int)sqrt(n) + 1;
for (int i = 3; i < limit; i += 2)
if (primes[i])
int step = i * 2;
for (int j = i * i; j <= n; j += step)
primes[j] = false;
return primes;
answered Apr 14 at 21:53
tinstaafl
5,492625
5,492625
This will not produce correct answers because it incorrectly indicates all even numbers are prime.
â Edward
Apr 15 at 11:27
Like my answer says, check even numbers without the sieve. Use it for only odd numbers..
â tinstaafl
Apr 15 at 11:29
But that leaves all of the even numbers (except 2) in the vector set incorrectly.
â Edward
Apr 15 at 11:30
Yes but none of the even numbers are used, only the odd ones.
â tinstaafl
Apr 15 at 11:32
add a comment |Â
This will not produce correct answers because it incorrectly indicates all even numbers are prime.
â Edward
Apr 15 at 11:27
Like my answer says, check even numbers without the sieve. Use it for only odd numbers..
â tinstaafl
Apr 15 at 11:29
But that leaves all of the even numbers (except 2) in the vector set incorrectly.
â Edward
Apr 15 at 11:30
Yes but none of the even numbers are used, only the odd ones.
â tinstaafl
Apr 15 at 11:32
This will not produce correct answers because it incorrectly indicates all even numbers are prime.
â Edward
Apr 15 at 11:27
This will not produce correct answers because it incorrectly indicates all even numbers are prime.
â Edward
Apr 15 at 11:27
Like my answer says, check even numbers without the sieve. Use it for only odd numbers..
â tinstaafl
Apr 15 at 11:29
Like my answer says, check even numbers without the sieve. Use it for only odd numbers..
â tinstaafl
Apr 15 at 11:29
But that leaves all of the even numbers (except 2) in the vector set incorrectly.
â Edward
Apr 15 at 11:30
But that leaves all of the even numbers (except 2) in the vector set incorrectly.
â Edward
Apr 15 at 11:30
Yes but none of the even numbers are used, only the odd ones.
â tinstaafl
Apr 15 at 11:32
Yes but none of the even numbers are used, only the odd ones.
â tinstaafl
Apr 15 at 11:32
add a comment |Â
up vote
3
down vote
With your j
loop in sieve_of_eratosthenes
you can start at i * i
, since all the multiples of i
with factors less than i
will have already been removed. And you can stop the i
loop when i * i > n
(a condition you can check when you find a new prime, before the j
loop).
add a comment |Â
up vote
3
down vote
With your j
loop in sieve_of_eratosthenes
you can start at i * i
, since all the multiples of i
with factors less than i
will have already been removed. And you can stop the i
loop when i * i > n
(a condition you can check when you find a new prime, before the j
loop).
add a comment |Â
up vote
3
down vote
up vote
3
down vote
With your j
loop in sieve_of_eratosthenes
you can start at i * i
, since all the multiples of i
with factors less than i
will have already been removed. And you can stop the i
loop when i * i > n
(a condition you can check when you find a new prime, before the j
loop).
With your j
loop in sieve_of_eratosthenes
you can start at i * i
, since all the multiples of i
with factors less than i
will have already been removed. And you can stop the i
loop when i * i > n
(a condition you can check when you find a new prime, before the j
loop).
answered Apr 14 at 19:44
1201ProgramAlarm
2,4752618
2,4752618
add a comment |Â
add a comment |Â
up vote
3
down vote
DonâÂÂt use the weird vector<bool>
. Using a vector of bytes will be faster, and using a bitset will give you the compactness if that was your intent.
Writing if (x==true)
is silly.
Use uniform initialization:
std::vector<std::byte> primes n+1, true ;
edit: (vector
has an init-list constructor in addition to other constructors. Touted as a feature when uniform init was promoted, it actually causes headscratching in code reviews exactly as I just fell into myself!)
use auto
(almost everywhere):
auto result= sieve(n);
I have doubts that astd::bitset
would be a sufficient data structure to implement a reasonably sized sieve of eratosthenes. Anyways, I'd agree going with thestd::vector<std::byte>
.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:07
@ÃÂìýÃÂÃ񠨝õῠstd::bitset can be of any length. It maintains an array of native-sized words, though PlaugerâÂÂs does seem to have optimization for small values of N.
â JDà Âugosz
Apr 14 at 10:46
May be you misunderstood me. Astd::bitset
can be build on top of a maxlong long
value. Astd::vector<std::bitset<64>>
might help to improve over astd::vector<bool>
while keeping the compactness in memory, you have to adapt your index calculations though.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:50
2
I'd advocate measuring rather than guessing when it comes to performance questions.
â Edward
Apr 14 at 15:16
1
@Edward, IIRC it will cause compilation error, as the second element requires conversion. I tried to compile it, but the error is too cryptic to understand :)
â Incomputable
Apr 14 at 16:34
 |Â
show 4 more comments
up vote
3
down vote
DonâÂÂt use the weird vector<bool>
. Using a vector of bytes will be faster, and using a bitset will give you the compactness if that was your intent.
Writing if (x==true)
is silly.
Use uniform initialization:
std::vector<std::byte> primes n+1, true ;
edit: (vector
has an init-list constructor in addition to other constructors. Touted as a feature when uniform init was promoted, it actually causes headscratching in code reviews exactly as I just fell into myself!)
use auto
(almost everywhere):
auto result= sieve(n);
I have doubts that astd::bitset
would be a sufficient data structure to implement a reasonably sized sieve of eratosthenes. Anyways, I'd agree going with thestd::vector<std::byte>
.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:07
@ÃÂìýÃÂÃ񠨝õῠstd::bitset can be of any length. It maintains an array of native-sized words, though PlaugerâÂÂs does seem to have optimization for small values of N.
â JDà Âugosz
Apr 14 at 10:46
May be you misunderstood me. Astd::bitset
can be build on top of a maxlong long
value. Astd::vector<std::bitset<64>>
might help to improve over astd::vector<bool>
while keeping the compactness in memory, you have to adapt your index calculations though.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:50
2
I'd advocate measuring rather than guessing when it comes to performance questions.
â Edward
Apr 14 at 15:16
1
@Edward, IIRC it will cause compilation error, as the second element requires conversion. I tried to compile it, but the error is too cryptic to understand :)
â Incomputable
Apr 14 at 16:34
 |Â
show 4 more comments
up vote
3
down vote
up vote
3
down vote
DonâÂÂt use the weird vector<bool>
. Using a vector of bytes will be faster, and using a bitset will give you the compactness if that was your intent.
Writing if (x==true)
is silly.
Use uniform initialization:
std::vector<std::byte> primes n+1, true ;
edit: (vector
has an init-list constructor in addition to other constructors. Touted as a feature when uniform init was promoted, it actually causes headscratching in code reviews exactly as I just fell into myself!)
use auto
(almost everywhere):
auto result= sieve(n);
DonâÂÂt use the weird vector<bool>
. Using a vector of bytes will be faster, and using a bitset will give you the compactness if that was your intent.
Writing if (x==true)
is silly.
Use uniform initialization:
std::vector<std::byte> primes n+1, true ;
edit: (vector
has an init-list constructor in addition to other constructors. Touted as a feature when uniform init was promoted, it actually causes headscratching in code reviews exactly as I just fell into myself!)
use auto
(almost everywhere):
auto result= sieve(n);
edited Apr 15 at 9:49
answered Apr 14 at 8:57
JDÃ Âugosz
5,047731
5,047731
I have doubts that astd::bitset
would be a sufficient data structure to implement a reasonably sized sieve of eratosthenes. Anyways, I'd agree going with thestd::vector<std::byte>
.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:07
@ÃÂìýÃÂÃ񠨝õῠstd::bitset can be of any length. It maintains an array of native-sized words, though PlaugerâÂÂs does seem to have optimization for small values of N.
â JDà Âugosz
Apr 14 at 10:46
May be you misunderstood me. Astd::bitset
can be build on top of a maxlong long
value. Astd::vector<std::bitset<64>>
might help to improve over astd::vector<bool>
while keeping the compactness in memory, you have to adapt your index calculations though.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:50
2
I'd advocate measuring rather than guessing when it comes to performance questions.
â Edward
Apr 14 at 15:16
1
@Edward, IIRC it will cause compilation error, as the second element requires conversion. I tried to compile it, but the error is too cryptic to understand :)
â Incomputable
Apr 14 at 16:34
 |Â
show 4 more comments
I have doubts that astd::bitset
would be a sufficient data structure to implement a reasonably sized sieve of eratosthenes. Anyways, I'd agree going with thestd::vector<std::byte>
.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:07
@ÃÂìýÃÂÃ񠨝õῠstd::bitset can be of any length. It maintains an array of native-sized words, though PlaugerâÂÂs does seem to have optimization for small values of N.
â JDà Âugosz
Apr 14 at 10:46
May be you misunderstood me. Astd::bitset
can be build on top of a maxlong long
value. Astd::vector<std::bitset<64>>
might help to improve over astd::vector<bool>
while keeping the compactness in memory, you have to adapt your index calculations though.
â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:50
2
I'd advocate measuring rather than guessing when it comes to performance questions.
â Edward
Apr 14 at 15:16
1
@Edward, IIRC it will cause compilation error, as the second element requires conversion. I tried to compile it, but the error is too cryptic to understand :)
â Incomputable
Apr 14 at 16:34
I have doubts that a
std::bitset
would be a sufficient data structure to implement a reasonably sized sieve of eratosthenes. Anyways, I'd agree going with the std::vector<std::byte>
.â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:07
I have doubts that a
std::bitset
would be a sufficient data structure to implement a reasonably sized sieve of eratosthenes. Anyways, I'd agree going with the std::vector<std::byte>
.â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:07
@ÃÂìýÃÂÃ񠨝õῠstd::bitset can be of any length. It maintains an array of native-sized words, though PlaugerâÂÂs does seem to have optimization for small values of N.
â JDà Âugosz
Apr 14 at 10:46
@ÃÂìýÃÂÃ񠨝õῠstd::bitset can be of any length. It maintains an array of native-sized words, though PlaugerâÂÂs does seem to have optimization for small values of N.
â JDà Âugosz
Apr 14 at 10:46
May be you misunderstood me. A
std::bitset
can be build on top of a max long long
value. A std::vector<std::bitset<64>>
might help to improve over a std::vector<bool>
while keeping the compactness in memory, you have to adapt your index calculations though.â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:50
May be you misunderstood me. A
std::bitset
can be build on top of a max long long
value. A std::vector<std::bitset<64>>
might help to improve over a std::vector<bool>
while keeping the compactness in memory, you have to adapt your index calculations though.â ÃÂìýÃÂñ á¿¥Ã栨Â
Apr 14 at 10:50
2
2
I'd advocate measuring rather than guessing when it comes to performance questions.
â Edward
Apr 14 at 15:16
I'd advocate measuring rather than guessing when it comes to performance questions.
â Edward
Apr 14 at 15:16
1
1
@Edward, IIRC it will cause compilation error, as the second element requires conversion. I tried to compile it, but the error is too cryptic to understand :)
â Incomputable
Apr 14 at 16:34
@Edward, IIRC it will cause compilation error, as the second element requires conversion. I tried to compile it, but the error is too cryptic to understand :)
â Incomputable
Apr 14 at 16:34
 |Â
show 4 more comments
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f192031%2fsieve-of-eratosthenes-with-stdvectorbool%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password