I found this old piece of code that I wrote while I was learning C a while back:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s <N>\n", argv[0]);
return 1;
}
size_t limit = strtoul(argv[1], (char **) NULL, 10);
size_t i, j, res = 0;
size_t isqrt = (size_t) sqrt(limit);
char* numbers = calloc(limit, 1);
for (i = 2; i <= isqrt; i++) {
if (numbers[i]) continue;
for (j = i*i; j < limit; j += i) numbers[j] = 1;
}
for (i = 2; i < limit; i++) {
if (!numbers[i]) ++res;
}
printf("%lu\n", res);
free(numbers);
return 0;
}
It's a sieve of Erathosthenes. Since now I started learning C++, I decided to rewrite it in C++11:
#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
int main(int argc, char *argv[]) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <N>" << std::endl;
return 1;
}
size_t limit = std::stoul(argv[1]);
size_t i, j, res = 0;
size_t isqrt = size_t (sqrt(limit));
std::unique_ptr<std::vector<bool> > sieve(new std::vector<bool>(limit));
for (i = 2; i <= isqrt; ++i) {
if (sieve->at(i)) continue;
for (j = i*i; j < limit; j += i) sieve->at(j) = 1;
}
for_each(sieve->cbegin() + 2, sieve->cend(), [&res](bool i) { res += !i; });
std::cout << res << std::endl;
return 0;
}
Is this the most idiomatic way to code in C++? I also tried to replace the first for loop with a for_each
and a functor that accepts sieve
, but in the end I decided it wasn't worth it and left it like that.
In both versions I am allocating on the heap because the sieve array/vector gets too big for the stack.
Interestingly, the C++ version is faster! I thought they were pretty much identical, but instead the C++ version wins by a large margin:
$ gcc --std=c99 -O3 erat.c -lm -o erat
$ time ./erat 1000000000
50847534
./erat 1000000000 11.50s user 0.41s system 99% cpu 11.927 total
$ g++ --std=c++14 -O2 erat.cpp -o erat2
$ time ./erat2 1000000000
50847534
./erat2 1000000000 8.52s user 0.02s system 99% cpu 8.554 total
Feedback on the C version is also welcomed!