prog.pl 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 10 July 2019
  4. # https://github.com/trizen
  5. # Positive integers k at which k/log_2(k) is at a record closeness to an integer, without actually being an integer.
  6. # https://oeis.org/A307099
  7. # Known terms:
  8. # 3, 10, 51, 189, 227, 356, 578, 677, 996, 3389, 38997, 69096, 149462, 2208495, 3459604, 4952236, 6710605, 48098656, 81762222, 419495413
  9. # Similar sequence for k/log(k):
  10. # 2, 5, 9, 13, 17, 163, 53453, 110673, 715533
  11. # https://oeis.org/A178805
  12. use 5.020;
  13. use strict;
  14. use warnings;
  15. use ntheory qw(:all);
  16. use experimental qw(signatures);
  17. my $prev = 1;
  18. #use Math::AnyNum qw(round);
  19. #use POSIX qw(log2 round);
  20. use Math::MPFR;
  21. my $PREC = 128;
  22. my $mpfr = Math::MPFR::Rmpfr_init2($PREC);
  23. my $ln2 = Math::MPFR::Rmpfr_init2($PREC);
  24. Math::MPFR::Rmpfr_const_log2($ln2, 0);
  25. sub log2 ($x) {
  26. Math::MPFR::Rmpfr_log_ui($mpfr, $x, 0);
  27. Math::MPFR::Rmpfr_div($mpfr, $mpfr, $ln2, 0);
  28. $mpfr;
  29. }
  30. sub round ($x) {
  31. Math::MPFR::Rmpfr_round($mpfr, $x);
  32. $mpfr;
  33. }
  34. sub bsearch_le ($left, $right, $callback) {
  35. my ($mid, $cmp);
  36. for (; ;) {
  37. $mid = int(($left + $right) / 2);
  38. $cmp = $callback->($mid) || return $mid;
  39. if ($cmp < 0) {
  40. $left = $mid + 1;
  41. $left > $right and last;
  42. }
  43. else {
  44. $right = $mid - 1;
  45. if ($left > $right) {
  46. $mid -= 1;
  47. last;
  48. }
  49. }
  50. }
  51. return $mid;
  52. }
  53. sub find_k($x) {
  54. my $k = bsearch_le($prev, 1e12, sub ($k) {
  55. $k/log2($k) <=> $x
  56. });
  57. my $t1 = $k/log2($k);
  58. my $t2 = ($k+1)/log2($k+1);
  59. if (abs($x - $t2) < abs($x - $t1)) {
  60. return ($t2, $k+1)
  61. }
  62. return ($t1, $k);
  63. }
  64. sub diff($x) { abs($x - round($x)) }
  65. local $| = 1;
  66. my $mindiff = 100000;
  67. foreach my $x(2..1e9) {
  68. my ($t, $k) = find_k($x);
  69. if (($k&($k-1)) == 0) {
  70. next;
  71. }
  72. my $dx = diff($t);
  73. if ($dx < $mindiff) {
  74. $mindiff = $dx;
  75. print($k, ", ");
  76. $prev = $k;
  77. }
  78. }
  79. say "Mindiff = $mindiff";