nth_prime_approx.pl 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #!/usr/bin/perl
  2. # A messy, but interesting approximation for the nth-prime.
  3. # Formulas from:
  4. # https://stackoverflow.com/a/9487883/1063770
  5. use 5.010;
  6. use strict;
  7. use warnings;
  8. use ntheory qw(nth_prime);
  9. my $sum1 = 0;
  10. my $sum2 = 0;
  11. for (my $n = 1e6 ; $n < 1e7 ; $n += 1e6) {
  12. my $p = nth_prime($n);
  13. # more than good approximation (experimental)
  14. my $p1 = int(
  15. 1 / 2 * (
  16. 3 - (8 + log(2.3)) * $n - $n**2 + 1 / 2 * (
  17. -1 + abs(
  18. -(1 / 2) + $n + sqrt(
  19. log(log($n) / log(2)) *
  20. (-log(log(2)) + log(log($n)) + (8 * log(3) * log(($n * log(8 * $n)) / log($n))) / log(2))
  21. ) / (2 * log(log(($n * log(8 * $n)) / log($n)) / log(2)))
  22. ) + abs(log($n) / log(3) + log(log(($n * log(8 * $n)) / log($n)) / log(2)) / log(2))
  23. ) * (
  24. 2 * abs(log(($n * log(8 * $n)) / log($n)) / log(3) + log(log(($n * log(8 * $n)) / log($n)) / log(2)) / log(2))
  25. + abs(
  26. 1 / log(log($n) / log(2)) * (
  27. log(log(3)) - log(log($n)) + 2 * $n * log(log($n) / log(2)) + sqrt(
  28. ((8 * log(3) * log($n)) / log(2) - log(log(2)) + log(log(($n * log(8 * $n)) / log($n)))) *
  29. log(log(($n * log(8 * $n)) / log($n)) / log(2))
  30. )
  31. )
  32. )
  33. )
  34. )
  35. );
  36. # good approximation
  37. my $p2 = int(
  38. 1 / 2 * (
  39. 8 - 8.7 * $n - $n**2 + 1 / 2 * (
  40. 2 * abs(log($n) / log(3) + log(log($n) / log(2)) / log(2)) + abs(
  41. (
  42. log(log(3)) -
  43. log(log($n)) +
  44. 2 * $n * log(log($n) / log(2)) +
  45. sqrt(((8 * log(3) * log($n)) / log(2) - log(log(2)) + log(log($n))) * log(log($n) / log(2)))
  46. ) / log(log($n) / log(2))
  47. )
  48. ) * (
  49. -1 + abs(log($n) / log(3) + log(log($n) / log(2)) / log(2)) + abs(
  50. -(1 / 2) +
  51. $n +
  52. sqrt(((8 * log(3) * log($n)) / log(2) - log(log(2)) + log(log($n))) * log(log($n) / log(2))) /
  53. (2 * log(log($n) / log(2)))
  54. )
  55. )
  56. )
  57. );
  58. $sum1 += $p / $p1;
  59. $sum2 += $p / $p2;
  60. say "P($n) -> ",join(" ", sprintf("%10s" x 3, $p, $p1, $p2), "\t", sprintf("%.5f", $p / $p1), sprintf("%.5f", $p / $p2));
  61. }
  62. say "P1 error: $sum1";
  63. say "P2 error: $sum2";
  64. __END__
  65. 29 36 29 0.80556 1.00000
  66. 15486041 15457742 15439431 1.00183 1.00302
  67. 32453039 32433008 32405572 1.00062 1.00146
  68. 49979893 49975183 49941439 1.00009 1.00077
  69. 67868153 67884333 67846000 0.99976 1.00033
  70. 86028343 86065798 86024104 0.99956 1.00005
  71. 104395451 104463936 104419831 0.99934 0.99977
  72. 122950039 123042040 122996293 0.99925 0.99962
  73. 141651127 141774052 141727310 0.99913 0.99946
  74. 160481437 160640508 160593326 0.99901 0.99930
  75. P1 error: 9.80416402659991
  76. P2 error: 10.0037856546587