More stringent restrictions:
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) upper = fn * (flogn + flog2n - 1.0 + ((flog2n-2.00)/flogn)); else if (n >= 178974) upper = fn * (flogn + flog2n - 1.0 + ((flog2n-1.95)/flogn)); else if (n >= 39017) upper = fn * (flogn + flog2n - 0.9484); else upper = fn * ( flogn + 0.6000 * flog2n ); if (upper >= (double) ULONG_MAX) { if (n <= 425656284035217743UL) return 18446744073709551557UL; fprintf(stderr, "nth_prime_upper overflow\n"; exit(-1); } return (unsigned long) ceil(upper); }
They should never be smaller than the actual nth_prime, should work for any 64-bit input and be an order of magnitude or closer compared to the formula from Robin given earlier (or Wimblik is a complicated formula with limited range). For my use, I have a slightly larger small column, so you can pull up the last estimate a bit. Technically, from the formulas, we could use floor () instead of ceil (), but I'm worried about accuracy.
Edit: Another option for improving this bit is to implement good graph boundaries (e.g. Axler 2014) and perform a binary search on them. My code for this method takes ~ 10 times longer than the above (still works in milliseconds), but can reduce the percentage of error by an order of magnitude.
If you need an estimate for the nth number, you can do:
- Cipolla 1902 (see Dusart 1999 page 12 or this document . I find three terms (m = 2) plus a third-order correction factor that is useful, but with a lot of members it fluctuates too much. The formula shown in the Wikipedia link is this formula (with m = 2). The two-term inverse or inverse Riemann R below will give better results.
- Calculate the upper and lower bounds of Dusart 2010 and average the results. Not so bad, although I suspect that using a weighted average will work better because the boundaries are not equally tight.
- li ^ {- 1} (n) Since li (n) is a decent approximation of a prime, the converse is a decent approximation of nth_prime. This and all the rest can be done quite quickly, like a binary function search.
- li ^ {- 1} (n) + li ^ {- 1} (sqrt (n)) / 4 Closer as it approaches R (n)
- R ^ {- 1} The inverse Riemann function R is the nearest average approximation. I know what is reasonable.
Finally, if you have a very fast method for counting numbers, for example, one of the LMO implementations (now there are three open source implementations), you can write a quick, accurate nth_prime method. The calculation of the 10 ^ 10th number can be performed in a few milliseconds, and the 10-13th in a couple of seconds (on a modern fast machine). The approximations are extremely fast on all sizes and work for a much larger number, but everyone has a different idea of ββwhat βbigβ means.
DanaJ Aug 22 '14 at 6:12 2014-08-22 06:12
source share