We\'re having a bit of fun here at work. It all started with one of the guys setting up a Hackintosh and we were wondering whether it was faster than a Windows Box of (nearl
It takes us under a second (2.4GHz) to generate the first 150000 prime numbers in Python using Sieve of Eratosthenes:
#!/usr/bin/env python
def iprimes_upto(limit):
"""Generate all prime numbers less then limit.
http://stackoverflow.com/questions/188425/project-euler-problem#193605
"""
is_prime = [True] * limit
for n in range(2, limit):
if is_prime[n]:
yield n
for i in range(n*n, limit, n): # start at ``n`` squared
is_prime[i] = False
def sup_prime(n):
"""Return an integer upper bound for p(n).
p(n) < n (log n + log log n - 1 + 1.8 log log n / log n)
where p(n) is the n-th prime.
http://primes.utm.edu/howmany.shtml#2
"""
from math import ceil, log
assert n >= 13
pn = n * (log(n) + log(log(n)) - 1 + 1.8 * log(log(n)) / log(n))
return int(ceil(pn))
if __name__ == '__main__':
import sys
max_number_of_primes = int(sys.argv[1]) if len(sys.argv) == 2 else 150000
primes = list(iprimes_upto(sup_prime(max_number_of_primes)))
print("Generated %d primes" % len(primes))
n = 100
print("The first %d primes are %s" % (n, primes[:n]))
Example:
$ python primes.py
Generated 153465 primes
The first 100 primes are [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197,
199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
467, 479, 487, 491, 499, 503, 509, 521, 523, 541]
You should be able to make the inner loop twice as fast by only evaluating the odd numbers. Not sure if this is valid Java, I'm used to C++, but I'm sure it can be adapted.
if (current != 2 && current % 2 == 0)
prime = false;
else {
for (int i = 3; i < top; i+=2) {
if (current % i == 0) {
prime = false;
break;
}
}
}
In C#:
class Program
{
static void Main(string[] args)
{
int count = 0;
int max = 150000;
int i = 2;
DateTime start = DateTime.Now;
while (count < max)
{
if (IsPrime(i))
{
count++;
}
i++;
}
DateTime end = DateTime.Now;
Console.WriteLine("Total time taken: " + (end - start).TotalSeconds.ToString() + " seconds");
Console.ReadLine();
}
static bool IsPrime(int n)
{
if (n < 4)
return true;
if (n % 2 == 0)
return false;
int s = (int)Math.Sqrt(n);
for (int i = 2; i <= s; i++)
if (n % i == 0)
return false;
return true;
}
}
Output:
Total time taken: 2.087 seconds
Here is a fast and simple solution:
Finding primes less than 1000000000; 50847534 were found in 23839 ms
//returns number of primes less than n
private static int getNumberOfPrimes(final int n)
{
if(n < 2)
return 0;
BitSet candidates = new BitSet(n - 1);
candidates.set(0, false);
candidates.set(1, false);
candidates.set(2, n);
for(int i = 2; i < n; i++)
if(candidates.get(i))
for(int j = i + i; j < n; j += i)
if(candidates.get(j) && j % i == 0)
candidates.set(j, false);
return candidates.cardinality();
}
I bet Miller-Rabin would be faster. If you test enough contiguous numbers it becomes deterministic, but I wouldn't even bother. Once a randomized algorithm reaches the point that its failure rate is equal to the likelihood that a CPU hiccup will cause a wrong result, it just doesn't matter any more.
Does the re-declaration of the variable prime
while (count < topPrime) {
boolean prime = true;
within the loop make it inefficient? (I assume it doesn't matter, since I would think Java would optimize this)
boolean prime;
while (count < topPrime) {
prime = true;