In short:
Given that a is coprime to b if GCD(a,b) = 1 (where GCD stands for great common divisor), how many positive integers below N are coprime to N?
Is there a clever way?
Not necessary stuff
Here is the dumbest way:
def count_coprime(N):
counter = 0
for n in xrange(1,N):
if gcd(n,N) == 1:
counter += 1
return counter
It works, but it is slow, and dumb. I’d like to use a clever and faster algorithm.
I tried to use prime factors and divisors of N but I always get something that doesn’t work with larger N.
I think the algorithm should be able to count them without calculating all of them like the dumbest algorithm does 😛
Edit
It seems I’ve found a working one:
def a_bit_more_clever_counter(N):
result = N - 1
factors = []
for factor, multiplicity in factorGenerator(N):
result -= N/factor - 1
for pf in factors:
if lcm(pf, factor) < N:
result += N/lcm(pf, factor) - 1
factors += [factor]
return result
where lcm is least common multiple. Does anyone have a better one?
Note
I’m using python, I think code should be readable even to who doesn’t know python, if you find anything that is not clear just ask in the comments. I’m interested in the algorithm and the math, the idea.
[Edit] One last thought, which (IMO) is important enough that I’ll put it at the beginning: if you’re collecting a bunch of totients at once, you can avoid a lot of redundant work. Don’t bother starting from large numbers to find their smaller factors — instead, iterate over the smaller factors and accumulate results for the larger numbers.
This takes just 8ms on my desktop.
The Wikipedia page on the Euler totient function has some nice mathematical results.
* by the second definition of trivial
This is perfect for an application of the Möbius inversion formula, a clever trick for inverting sums of this exact form.
This leads naturally to the code
There exist better implementations of the Möbius function, and it could be memoized for speed, but this should be easy enough to follow.
The more obvious computation of the totient function is
In other words, fully factor the number into unique primes and exponents, and do a simple multiplication from there.
Again, there exist better implementations of
prime_factors, but this is meant for easy reading.# helper functions# OP's first attempt# OP's second attempt# Möbius inversion# traditional formula# traditional formula, no divisionUsing this code to calculate the totients of all numbers from 1 to 9999 on my desktop, averaging over 5 runs,
totient1takes forevertotient2takes 10stotient3takes 1.3stotient4takes 1.3s