Having a little trouble trying calculate the number of trailing zeros in a factorial of a given number. This is one of the challenges from Codewars- can\'t get mine to pass.
So, now that @Spunden has so artfully let the cat out of the bag, here's one way to implement it.
Code
def zeros(n)
return 0 if n.zero?
k = (Math.log(n)/Math.log(5)).to_i
m = 5**k
n*(m-1)/(4*m)
end
Examples
zeros(3) #=> 0
zeros(5) #=> 1
zeros(12) #=> 2
zeros(15) #=> 3
zeros(20) #=> 4
zeros(25) #=> 6
zeros(70) #=> 16
zeros(75) #=> 18
zeros(120) #=> 28
zeros(125) #=> 31
Explanation
Suppose n = 128
.
Then each number between one and 128
(inclusive) that is divisible by 5^1=>5
provides at least one factor, and there are 128/5 => 25
such numbers. Of these, the only ones that provide more than one factor are those divisible by 5^2=>25
, of which there are 128/25 => 5
(25, 50, 75, 100, 125
). Of those, there is but 128/125 => 1
that provides more than two factors, and since 125/(5^4) => 0
, no numbers contribute more than three divisors. Hence, the total number of five divisors is:
128/5 + 128/25 + 128/125 #=> 31
(Note that, for 125
, which has three divisors of 5
, one is counted in each of these three terms; for 25
, 50
, etc., which each have two factors of 5
, one is counted in each of the first terms.)
For arbitrary n
, we first compute the highest power k
for which:
5**k <= n
which is:
k <= Math.log(n)/Math.log(5)
so the largest such value is:
k = (Math.log(n)/Math.log(5)).to_i
As @spundun noted, you could also calculate k
by simply iterating, e.g.,
last = 1
(0..1.0/0).find { |i| (last *= 5) > n }
The total number of factors of five is therefore
(n/5) + (n/25) +...+ (n/5**k)
Defining:
r = 1/5,
this sum is seen to be:
n * s
where
s = r + r**2 +...+ r**k
The value of s
is the sum of the terms of a geometric series. I forget the formula for that, but recall how it's derived:
s = r + r**2 +...+ r**k
sr = r**2 +...+ r**(k+1)
s-sr = r*(1-r**k)
s = r*(1-r**k)/(1-r)
I then did some rearrangement so that only only integer arithmetic would be used to calculate the result.