partial_sums_of_sigma_function.sf 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #!/usr/bin/ruby
  2. # Daniel "Trizen" Șuteu
  3. # Date: 07 November 2018
  4. # https://github.com/trizen
  5. # Formula in terms of Bernoulli polynomials for computing the partial-sums of:
  6. #
  7. # a(n) = Sum_{k=1..n} sigma_j(k)
  8. #
  9. # for some fixed j >= 0, without using the sigma function.
  10. # Formulas:
  11. # a(n) = Sum_{k=1..n} sigma_j(k)
  12. # = Sum_{k=1..n} Sum_{d|k} d^j
  13. # = Sum_{k=1..n} Sum_{b=1..floor(n/k)} b^j
  14. # = Sum_{k=1..n} (Bernoulli(j+1, 1+floor(n/k)) - Bernoulli(j+1, 0))/(j+1)
  15. # = floor((n+1)/2) + Sum_{j=1..floor(n/2)} (Bernoulli(j+1, 1+floor(n/k)) - Bernoulli(j+1, 0))/(j+1)
  16. #
  17. # where Bernoulli(n,x) are the Bernoulli polynomials.
  18. # Alternative formulas:
  19. # a(n) = Sum_{k=1..n} sigma_j(k)
  20. # = Sum_{k=1..n} k^j * floor(n/k)
  21. # = (Bernoulli(j+1, n+1) - Bernoulli(j+1, 1+floor(n/2)))/(j+1) + Sum_{k=1..floor(n/2)} k^j * floor(n/k)
  22. # See also:
  23. # https://en.wikipedia.org/wiki/Divisor_function
  24. # https://en.wikipedia.org/wiki/Faulhaber's_formula
  25. # https://en.wikipedia.org/wiki/Bernoulli_polynomials
  26. # https://trizenx.blogspot.com/2018/08/interesting-formulas-and-exercises-in.html
  27. func sigma_partial_sum(n, j) {
  28. sum(1..n, {|k| k.sigma(j) })
  29. }
  30. func faulhaber_sigma_partial_sum(n, j) {
  31. floor((n+1)/2) + sum(1..floor(n/2), {|k|
  32. faulhaber_sum(floor(n / k), j)
  33. })
  34. }
  35. func bernoulli_sigma_partial_sum(n, j) {
  36. var t = bernoulli(j+1)
  37. floor((n+1)/2) + sum(1..floor(n/2), {|k|
  38. (bernoulli(j+1, 1+floor(n / k)) - t) / (j+1)
  39. })
  40. }
  41. func faulhaber_alternative_sigma_partial_sum(n, j) {
  42. faulhaber_sum(n, j) - faulhaber_sum(floor(n/2), j) + sum(1..floor(n/2), {|k|
  43. k**j * floor(n/k)
  44. })
  45. }
  46. func bernoulli_alternative_sigma_partial_sum(n, j) {
  47. (bernoulli(j+1, n+1) - bernoulli(j+1, 1+floor(n/2))) / (j+1) + sum(1..floor(n/2), {|k|
  48. k**j * floor(n/k)
  49. })
  50. }
  51. #
  52. ## Run some tests
  53. #
  54. for j in (1..10) {
  55. var n = 1000.irand
  56. var a = sigma_partial_sum(n, j)
  57. var b = bernoulli_sigma_partial_sum(n, j)
  58. var c = faulhaber_sigma_partial_sum(n, j)
  59. var d = faulhaber_alternative_sigma_partial_sum(n, j)
  60. var e = bernoulli_alternative_sigma_partial_sum(n, j)
  61. assert_eq(a, b)
  62. assert_eq(a, c)
  63. assert_eq(a, d)
  64. assert_eq(a, e)
  65. say "Sum_{k=1..#{n}} sigma_#{j}(k) = #{b}"
  66. }
  67. __END__
  68. Sum_{k=1..439} sigma_1(k) = 158390
  69. Sum_{k=1..606} sigma_2(k) = 89428845
  70. Sum_{k=1..906} sigma_3(k) = 182745921247
  71. Sum_{k=1..158} sigma_4(k) = 20751543588
  72. Sum_{k=1..591} sigma_5(k) = 7261290636306925
  73. Sum_{k=1..840} sigma_6(k) = 42686645719301011492
  74. Sum_{k=1..333} sigma_7(k) = 19205081250504734854
  75. Sum_{k=1..327} sigma_8(k) = 4825111439384649236832
  76. Sum_{k=1..472} sigma_9(k) = 55519692608089816684245494
  77. Sum_{k=1..432} sigma_10(k) = 9008681557899400667788631360