在这种方法中,数字是否检查了素数?

时间:2013-12-23 18:41:19

标签: ruby primes

我发现这是一种找到数字最高素因子的方法。 然而,内在的黑暗神秘 - 包括我曾经读过的东西被禁止 - 改变了循环中循环的条件。

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

所以我看到(有点)如何找到因素。 但在这些方面的位置是检查因素以确保它是素数?

我错过了什么数学见解?

由于

3 个答案:

答案 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有自己,有xy因素1 < x, y < f成立。
  • 因此,xy也必须是N 的因素,xy都是小于f
  • 这是一个矛盾,因为我们说fN的最小因素。
  • 因此,我们对f的原始假设是错误的,f必须是素数。

我通过检查循环的不变得到了这个结果,我将在适当的时候添加到这个答案。

编辑:关于不变量的注释

循环的不变量是在循环运行之前,期间和之后保持为真的谓词条件,我们可以用它来证明循环为我们提供了我们想要的答案。

对于我们的循环,我们必须跟踪一个简单的不变量,sqi = i**2只是表明sqi必须始终保持{{1}的平方值}。这个不变量的存在是为了让我们每次重新计算正方形以与n进行比较。 (顺便说一下,这就是为什么我在我的方法中将其更改为i递增的原因,否则您可能会将2 * i + 1置于循环条件中。

不变量的另一部分是i*i哈希(在数学上我将其视为一组数字)是数字factors的一组因子,k

不变量的最后且最重要的部分是n * k = orig,其中i <= ff的最小因子。 (这意味着n仅在n % i = 0时,这意味着循环始终找到i = f的最小因子,这是n}的主要因素。

编写不变量只是成功的一半,我们还需要证明我们的方法始终遵循它:

  • 不变量的第一部分很简单,因为无论何时我们更新n我们都会正确更新i,它们分别以sqi2开头。< / LI>
  • 第二部分同样非常简单,因为我们只添加4作为因素 i是正确的,同时我们将n % i == 0除以n,以确保从i中移除添加到k的因子

  • 现在让我们看看不变量的一部分,它对确保列表只包含素数因子至关重要。好吧,从n开始,这是任何一个中最小的因素 数字(不包括i = 2,因为它涉及素性时的尴尬)。然后我们需要确保尽可能将1增加为 late 。即当我们确信它不再是一个因素。

    我们的代码仅在i不是i时增加n。如果之前保留不变量,则表示i <= fi不是因素,因此 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,它的所有主要因子在先前的迭代中都已经被“排除”了。