我有这个代码似乎适用于正常时间段内的6-8位数字。 当我输入更大的值时,数量会变得非常糟糕。完成需要4个多小时。 这是我的代码。
#Fermat's factorization method
def get_largest_prime n
t=(Math.sqrt(n)+1).floor
k=0
prime_numbers=[]
while (t+k)<n
element = (t+k)**2-n
if is_integer? Math.sqrt(element)
#store prime numbers
prime_numbers << t+k+Math.sqrt(element)
prime_numbers << t+k-Math.sqrt(element)
#puts "Prime Factors of #{n} are: #{t+k+Math.sqrt(element)} and #{t+k-Math.sqrt(element)}"
end
k+=1
end
puts "Prime Factors: "+prime_numbers.to_s
end
#making sure 450.0 is 450, for example.
def is_integer? number
number.to_i == number ? true : false
end
get_largest_prime 600851475143
运行此操作需要4个多小时。
但是将它作为值'600851'或'60085167'运行并不需要花费很多时间。有什么帮助吗?
答案 0 :(得分:2)
首先请注意,费马因子分解通常不会给出主要因素。
然后,您运行它直到t+k >= n
,这意味着您运行while
循环n - t
次,因为t
大致是sqrt(n)
,这是一个O(n)
算法。对于较大的n
如600851475143(约6 * 10 ^ 11),这必然需要很长时间。
您需要更改算法。当你找到一对除数(都大于1)时,将它们递归分解。如果找到的因子中较小的一个是1,那么这是一个主要因素。
这样做(原谅不好的风格,我几乎不知道红宝石):
#Fermat's factorization method
def get_largest_prime n
t=(Math.sqrt(n)+1).floor
k=0
prime_numbers=[]
while (t+k)<n
element = (t+k)**2-n
if is_integer? Math.sqrt(element)
#store prime numbers
a = t+k+Math.sqrt(element)
b = t+k-Math.sqrt(element)
if b == 1
prime_numbers << a
break
end
prime_numbers += get_largest_prime a
prime_numbers += get_largest_prime b
break
#puts "Prime Factors of #{n} are: #{t+k+Math.sqrt(element)} and #{t+k-Math.sqrt(element)}"
end
k+=1
end
return prime_numbers
end
#making sure 450.0 is 450, for example.
def is_integer? number
number.to_i == number ? true : false
end
a = get_largest_prime 600851475143
puts "Prime Factors: "+a.to_s
快速解决问题。
但是,对于没有除数接近平方根的数字,仍需要很长时间。
通过试验划分的标准因子分解具有更好的最坏情况行为(O(sqrt(n)
最坏情况)。不过,混合方法可能比纯试验分区略快。
答案 1 :(得分:1)
这里有两个效果:
1)当Ruby中的整数大于2 ** 31时,它会使用不同且速度较慢的表示
2)一旦数量变得足够大,就没有已知的因子分解算法最终表现不佳 - 从技术上讲,它们都比你想要分解的数字(数字的位数)的任何多项式都慢得多。 / p>
您可以使用
加快速度Math.sqrt(element)
以下。在所有测试之前,将结果分配给变量。请注意,这不会“修复”您的问题。最终它的运行速度不会超过一定数量 - 即使你将所有内容都转移到了C(尽管在C变慢之前你可能会挤出几个额外的数字)
答案 2 :(得分:0)
可能您可以尝试下面的代码。
def prime_factor limit
(2..Math.sqrt(limit).to_i).inject([]) do |memo, var|
memo << var if limit % var == 0 and !memo.any? {|d| var % d == 0}
memo
end
end
prime_result = prime_factor 600851475143
puts prime_result.max
答案 3 :(得分:0)
您使用的循环越少,代码运行的速度就越快;-)(减少cpu周期)。尝试像on this program that finds the largest prime factor
那样递归地完成所有事情