Sieve of eratosthenes with std::vector

The name of the pictureThe name of the pictureThe name of the pictureClash 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';







share|improve this question



























    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';







    share|improve this question























      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';







      share|improve this question













      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';









      share|improve this question












      share|improve this question




      share|improve this question








      edited Apr 15 at 6:12









      Deduplicator

      9,8601844




      9,8601844









      asked Apr 14 at 8:34









      coder

      911425




      911425




















          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.
          timing results byte vs boolmemory results byte vs bool






          share|improve this answer






























            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;






            share|improve this answer





















            • 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

















            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).






            share|improve this answer




























              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);





              share|improve this answer























              • 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










              • 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




                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











              Your Answer




              StackExchange.ifUsing("editor", function ()
              return StackExchange.using("mathjaxEditing", function ()
              StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
              StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
              );
              );
              , "mathjax-editing");

              StackExchange.ifUsing("editor", function ()
              StackExchange.using("externalEditor", function ()
              StackExchange.using("snippets", function ()
              StackExchange.snippets.init();
              );
              );
              , "code-snippets");

              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "196"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              convertImagesToLinks: false,
              noModals: false,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );








               

              draft saved


              draft discarded


















              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






























              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.
              timing results byte vs boolmemory results byte vs bool






              share|improve this answer



























                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.
                timing results byte vs boolmemory results byte vs bool






                share|improve this answer

























                  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.
                  timing results byte vs boolmemory results byte vs bool






                  share|improve this answer















                  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.
                  timing results byte vs boolmemory results byte vs bool







                  share|improve this answer















                  share|improve this answer



                  share|improve this answer








                  edited Apr 15 at 15:33


























                  answered Apr 15 at 14:00









                  Edward

                  44k374201




                  44k374201






















                      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;






                      share|improve this answer





















                      • 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














                      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;






                      share|improve this answer





















                      • 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












                      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;






                      share|improve this answer













                      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;







                      share|improve this answer













                      share|improve this answer



                      share|improve this answer











                      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
















                      • 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










                      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).






                      share|improve this answer

























                        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).






                        share|improve this answer























                          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).






                          share|improve this answer













                          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).







                          share|improve this answer













                          share|improve this answer



                          share|improve this answer











                          answered Apr 14 at 19:44









                          1201ProgramAlarm

                          2,4752618




                          2,4752618




















                              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);





                              share|improve this answer























                              • 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










                              • 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




                                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















                              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);





                              share|improve this answer























                              • 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










                              • 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




                                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













                              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);





                              share|improve this answer















                              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);






                              share|improve this answer















                              share|improve this answer



                              share|improve this answer








                              edited Apr 15 at 9:49


























                              answered Apr 14 at 8:57









                              JDługosz

                              5,047731




                              5,047731











                              • 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










                              • 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




                                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











                              • @πάνταῥεῖ 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






                              • 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













                               

                              draft saved


                              draft discarded


























                               


                              draft saved


                              draft discarded














                              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













































































                              Popular posts from this blog

                              Greedy Best First Search implementation in Rust

                              Function to Return a JSON Like Objects Using VBA Collections and Arrays

                              C++11 CLH Lock Implementation