sum_of_digits_subquadratic_algorithm.sf 878 B

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. #!/usr/bin/ruby
  2. # Subquadratic algorithm for computing the sum of digits of a given integer in a given base.
  3. # Based on the FastIntegerOutput algorithm presented in the book:
  4. #
  5. # Modern Computer Arithmetic
  6. # - by Richard P. Brent and Paul Zimmermann
  7. #
  8. func FastSumOfDigits(A, B) {
  9. # Find k such that B^(2k - 2) <= A < B^(2k)
  10. var k = (A.ilog(B)>>1 + 1)
  11. func (A, k) {
  12. if (A < B) {
  13. return A
  14. }
  15. var (Q,R) = A.divmod(B**k)
  16. var t = (k+1)>>1
  17. __FUNC__(R, t) + __FUNC__(Q, t)
  18. }(A, k)
  19. }
  20. for B in (2..100) { # run some tests
  21. var N = 1e20.irand
  22. var a = N.sumdigits(B)
  23. var b = FastSumOfDigits(N, B)
  24. assert_eq(a, b)
  25. }
  26. say FastSumOfDigits(5040, 10) #=> 9
  27. say FastSumOfDigits(5040, 11) #=> 20
  28. say FastSumOfDigits(5040, 12) #=> 13
  29. say FastSumOfDigits(5040, 13) #=> 24