This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author tim.peters
Recipients kellerfuchs, mark.dickinson, rhettinger, serhiy.storchaka, steven.daprano, tim.peters
Date 2018-12-14.19:37:40
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1544816260.42.0.788709270274.issue35431@psf.upfronthosting.co.za>
In-reply-to
Content
Just for fun, here's a gonzo implementation (without arg-checking) using ideas from the sketch. All factors of 2 are shifted out first, and all divisions are done before any multiplies. For large arguments, this can run much faster than a dumb loop. For example, combp(10**100, 400) takes about a quarter the time of a dumb-loop divide-each-time-thru implementation. # Return number of trailing zeroes in `n`. def tzc(n): result = 0 if n: mask = 1 while n & mask == 0: result += 1 mask <<= 1 return result # Return exponent of prime `p` in prime factorization of # factorial(k). def facexp(k, p): result = 0 k //= p while k: result += k k //= p return result def combp(n, k): from heapq import heappop, heapify, heapreplace if n-k < k: k = n-k if k == 0: return 1 if k == 1: return n firstnum = n - k + 1 nums = list(range(firstnum, n+1)) assert len(nums) == k # Shift all factors of 2 out of numerators. shift2 = 0 for i in range(firstnum & 1, k, 2): val = nums[i] c = tzc(val) assert c nums[i] = val >> c shift2 += c shift2 -= facexp(k, 2) # cancel all 2's in factorial(k) assert shift2 >= 0 # Any prime generator is fine here. `k` can't be # huge, and we only want the primes through `k`. pgen = psieve() p = next(pgen) assert p == 2 for p in pgen: if p > k: break pcount = facexp(k, p) assert pcount # Divide that many p's out of numerators. i = firstnum % p if i: i = p - i for i in range(i, k, p): val, r = divmod(nums[i], p) assert r == 0 pcount -= 1 while pcount: val2, r = divmod(val, p) if r: break else: val = val2 pcount -= 1 nums[i] = val if pcount == 0: break assert pcount == 0 heapify(nums) while len(nums) > 1: a = heappop(nums) heapreplace(nums, a * nums[0]) return nums[0] << shift2 I'm NOT suggesting to adopt this. Just for history in the unlikely case there's worldwide demand for faster `comb` of silly arguments ;-)
History
Date User Action Args
2018-12-14 19:37:40tim.peterssetrecipients: + tim.peters, rhettinger, mark.dickinson, steven.daprano, serhiy.storchaka, kellerfuchs
2018-12-14 19:37:40tim.peterssetmessageid: <1544816260.42.0.788709270274.issue35431@psf.upfronthosting.co.za>
2018-12-14 19:37:40tim.peterslinkissue35431 messages
2018-12-14 19:37:40tim.peterscreate