重写分解质因数这个case,因为原来的代码太难看,还有一点错误
一、编写最基本的代码
最开始我是这么想的,从2开始循环,一直到待分解的那个数为止。用待分解的数去除这个循环变量,如果余数是0,那么这就是待分解的数的一个因数了。
得益于ruby的快捷,我们想到了就可以马上开始做。
def dpf(x)
result = []
2.upto(x) do |i|
loop do
if x % i ==0
result << i
x /= i
else
break
end
end
end
result << x unless x == 1
return result
end这样分解出来的质因数都存放在result数组里了。
现在我们就可以运行这一小段程序试试。看起来没问题,不过这也太慢了!
二、优化程序
我们不难发现,大于待分解的数的平方根的数不可能是这个数的质因数的,于是我们可以让他只循环到这个数的平方根。
def dpf(x)
#......
2.upto(x**0.5) do |i|
#......
end
end这样程序就快了不少。来试试他的效率吧!
先算10,他马上就给出了"10 = 2*5"
算100,他也马上给出了"100 = 2*2*5*5"
算1000,算10000
...
等等!
我们好像发现了一个规律。1*10**n = n个2乘n个5。如果我们把这个规律也交给我们的程序的话,那么它看起来就聪明多了。
def dpf(x)
result, xs = [], x.to_s
if start = (xs =~ /0+$/)
zeroc = xs.length - start
result = [2,5] * zeroc
x = xs[0,start].to_i
end
#.......
end这下对于10的倍数快了些,但对于其他的数还是没有改进。
继续想....
分解质因数,分解质因数,所以不是质数的数就不在我们的考虑范围之内了
事实上,除了2以外,其他的偶数都不是质数。
我们只需要考虑2,和其它奇数,跳过其它偶数
def dpf(x)
#......
loop do
if x % 2 ==0
result << 2
x /= 2
else
break
end
end
3.step((x**0.5).to_i,2) do |i|
loop do
if x % i ==0
result << i
x /= i
else
break
end
end
end
result << x unless x == 1
return result.sort!
end最后,我们的分解质因数的小case的完整的代码在这里
def dpf(x)
raise ZeroDivisionError if x == 0
result, xs = [], x.to_s
if start = (xs =~ /0+$/)
zeroc = xs.length - start
result = [2,5] * zeroc
x = xs[0,start].to_i
end
loop do
if x % 2 ==0
result << 2
x /= 2
else
break
end
end
3.step((x**0.5).to_i,2) do |i|
loop do
if x % i ==0
result << i
x /= i
else
break
end
end
end
result << x unless x == 1
return result.sort!
end[
本帖最后由 xavier 于 2008-5-17 11:29 编辑 ]