我发现这是一种找到数字最高素因子的方法。 然而,内在的黑暗神秘 - 包括我曾经读过的东西被禁止 - 改变了循环中循环的条件。
def factorize(orig) # 600851475143
factors = Hash.new(0)
n = orig
i = 2
sqi = 4
while sqi <= n do
if n % i == 0
n /= i
factors[i] = true
puts "Found factor #{i}"
end
i += 1
sqi = i**2
puts "sqi is #{sqi}"
end
if (n != 1) && (n != orig)
factors[n] = true
end
p factors
end
puts factorize(600851475143).keys.max
所以我看到(有点)如何找到因素。 但在这些方面的位置是检查因素以确保它是素数?
我错过了什么数学见解?
由于
答案 0 :(得分:2)
你的方法稍有不妥(稍微)。它应该是这样的:
def factorize(orig)
factors = Hash.new(0)
n, i, sqi = orig, 2, 4
while sqi <= n do
if n % i == 0
n /= i
factors[i] = true
puts "Found factor #{i}"
else
sqi += 2 * i + 1
i += 1
end
puts "sqi is #{sqi}"
end
if (n != 1) && (n != orig)
factors[n] = true
end
p factors
end
现在的区别在于,当i
不因素sqi
时,我只会增加i
(和n
)。这是因为,与之前突出显示的16
示例一样,一个数字可以包含任意一个素数因子的多个实例,因此我们应该继续检查一个数字,直到它不再是一个因素。
现在这个方法确保保证素数,因为它总是找到数字的最小因子(相反,它只会增加它检查的因子,如果它不再是因素,这是说同样的事情)。当然,数字中最小的因子必须是素数:
通过矛盾证明数字的最小因子是素数。
f
的最小因素N
不素数。f
有自己,有x
和y
因素1 < x, y < f
成立。x
和y
也必须是N
和的因素,x
,y
都是小于f
!f
是N
的最小因素。f
的原始假设是错误的,f
必须是素数。我通过检查循环的不变得到了这个结果,我将在适当的时候添加到这个答案。
循环的不变量是在循环运行之前,期间和之后保持为真的谓词条件,我们可以用它来证明循环为我们提供了我们想要的答案。
对于我们的循环,我们必须跟踪一个简单的不变量,sqi = i**2
只是表明sqi
必须始终保持{{1}的平方值}。这个不变量的存在是为了让我们每次重新计算正方形以与n进行比较。 (顺便说一下,这就是为什么我在我的方法中将其更改为i
递增的原因,否则您可能会将2 * i + 1
置于循环条件中。
不变量的另一部分是i*i
哈希(在数学上我将其视为一组数字)是数字factors
的一组因子,k
不变量的最后且最重要的部分是n * k = orig
,其中i <= f
是f
的最小因子。 (这意味着n
仅在n % i = 0
时,这意味着循环始终找到i = f
的最小因子,这是n
}的主要因素。
编写不变量只是成功的一半,我们还需要证明我们的方法始终遵循它:
n
我们都会正确更新i
,它们分别以sqi
和2
开头。< / LI>
第二部分同样非常简单,因为我们只添加4
作为因素
i
是正确的,同时我们将n % i == 0
除以n
,以确保从i
中移除添加到k
的因子
现在让我们看看不变量的一部分,它对确保列表只包含素数因子至关重要。好吧,从n
开始,这是任何一个中最小的因素
数字(不包括i = 2
,因为它涉及素性时的尴尬)。然后我们需要确保尽可能将1
增加为 late 。即当我们确信它不再是一个因素。
我们的代码仅在i
不是i
时增加n
。如果之前保留不变量,则表示i <= f
和i
不是因素,因此 i < f
。因此,正确的行为是递增以使i
更接近f
。
这个逻辑足以暗示当i
不是一个因素时,我们应该增加它,但不足以表明我们不应该总是递增i
,对于我们需要下一条逻辑:如果i
因素为n
,则表示 i = f
,但是,它没有告诉我们下一个最小因子是否严格大于f
(正如我们在16
看到的那样,下一个最小因子可能等于以前的)。所以这意味着如果它是一个因素,我们不应该增加i
,因为这样做可能会让我们错过下一个最小的因素。
我希望这一点让你相信程序的正确性。也可以使用嵌套的while循环编写factorize
,我觉得这可能有点简单,但它们的工作基本相同。
答案 1 :(得分:1)
if n % i == 0
检查n是否可被i
整除。如果是,那么它设置factors[i] = true
,如果一个数字没有因素(除了它自己和一个);然后它是素数。
答案 2 :(得分:0)
因素未检查以确保它是素数。这就是为什么它为orig == 32打破(给出非素因子):
Found factor 2
sqi is 9
sqi is 16
Found factor 4
sqi is 25
{2=>true, 4=>true}
4
可以修复(同时保留相同的逻辑,即没有重大的重写),将if n % i == 0
替换为while n % i == 0 do
(也就是说,在可能的情况下将n除以i):那么到时候我们如果达到复合i,它的所有主要因子在先前的迭代中都已经被“排除”了。