Is there a function which will return the approximate value of the n th prime? I think this would be something like an approximate inverse prime counting function. For example, if I gave this function 25 it would return a number around 100, or if I gave this function 1000 it would return a number around 8000. I don't care if the number returned is prime or not, but I do want it to be fast (so no generating the first n prime numbers to return the n th.)
I would like this so that I can generate the first n prime numbers using a sieve (Eratosthenes or Atkin). Therefore, the approximation for n th the would ideally never underestimate the value of the actual n th prime.
(Update: see my answer for a good method of finding the upper bound of the n th prime number.)
An easy way to determine if a number is prime is by trial division: divide the number n by all the integers less than n, and if no exact divisors–other than 1–are found, then n is prime.
Solution: First five prime numbers are 2, 3, 5, 7 and 11. The mean or the average formula is = Sum/no. = (2 + 3 + 5 + 7 +11)/5 = 5.6. Example 2: Find the average of 56, 41, 59, 52, 42 and 44.
Therefore, the factors of 16 are 1, 2, 4, 8, and 16 and the prime factorization of 16 is 16 = 2 × 2 × 2 × 2.
The prime numbers from 1 to 100 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.
Tighter bounds:
static const unsigned short primes_small[] = {0,2,3,5,7,11};
static unsigned long nth_prime_upper(unsigned long n) {
double fn = (double) n;
double flogn, flog2n, upper;
if (n < 6) return primes_small[n];
flogn = log(n);
flog2n = log(flogn);
if (n >= 688383) /* Dusart 2010 page 2 */
upper = fn * (flogn + flog2n - 1.0 + ((flog2n-2.00)/flogn));
else if (n >= 178974) /* Dusart 2010 page 7 */
upper = fn * (flogn + flog2n - 1.0 + ((flog2n-1.95)/flogn));
else if (n >= 39017) /* Dusart 1999 page 14 */
upper = fn * (flogn + flog2n - 0.9484);
else /* Modified from Robin 1983 for 6-39016 _only_ */
upper = fn * ( flogn + 0.6000 * flog2n );
if (upper >= (double) ULONG_MAX) {
/* Adjust this as needed for your type and exception method */
if (n <= 425656284035217743UL) return 18446744073709551557UL;
fprintf(stderr, "nth_prime_upper overflow\n"; exit(-1);
}
return (unsigned long) ceil(upper);
}
These should not ever be less than the actual nth_prime, should work for any 64-bit input, and be an order of magnitude or more closer than the formula from Robin given earlier (or Wimblik's complicated range-limited formula). For my use I have a slightly larger small primes table so can tighten up the last estimate a bit more. Technically from the formulas we could use floor() instead of ceil() but I worry about precision.
Edit: Another option for improving this a bit is implementing good prime count bounds (e.g. Axler 2014) and doing a binary search on them. My code for this method takes ~10x longer than the above (still running in under a millisecond), but can reduce the error percentage by an order of magnitude.
If you want an estimate for the nth prime, you can do:
Lastly, if you have a very fast prime count method such as one of the LMO implementations (there are three open source implementations now), you can write a fast precise nth_prime method. Computing the 10^10th prime can be done in a few milliseconds, and the 10^13th in a couple seconds (on a modern fast machine). The approximations are extremely fast at all sizes and work for far larger numbers, but everyone has a different idea of what "large" means.
Thanks for all of those answers. I suspected there was something fairly simple like that, but I couldn't find it at the time. I've done a bit more research too.
As I want it for a sieve to generate the first n prime numbers, I want the approximation to be greater than or equal to the nth prime. (Therefore, I want the upper bound of the nth prime number.)
Wikipedia gives the following upper bound for n >= 6
p_n <= n log n + n log log n (1)
where p_n
is the nth prime, and log
is the natural logarithm. This is a good start, but it can overestimate by a not inconsiderable amount. This article in The College Mathematics Journal gives a tighter upper bound for n >= 7022
p_n <= n log n + n (log log n - 0.9385) (2)
This is a much tighter bound as the following table shows
n p_n approx 1 error% approx 2 error%
1 2
10 29 31 6.90
100 541 613 13.31
1000 7919 8840 11.63
10000 104729 114306 9.14 104921 0.18
100000 1299709 1395639 7.38 1301789 0.16
1000000 15485863 16441302 6.17 15502802 0.11
10000000 179424673 188980382 5.33 179595382 0.10
I implemented my nth prime approximation function to use the second approximation for n >= 7022
, the first approximation for 6 <= n < 7022
, and an array lookup for the first 5 prime numbers.
(Although the first method isn't a very tight bound, especially for the range where I use it, I am not concerned as I want this for a sieve, and a sieve of smaller numbers is computationally cheap.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With