为什么 Ruby 中有这个百分比错误?初学者学习

Why this % Error in Ruby ? Beginner Learning

我昨天刚开始Ruby。 我在网上看到了一些基础知识并开始做一些初学者编码挑战,其中一个要求寻找素数。我尽量不使用 Ruby 中已有的 prime 功能。 我想我差不多搞定了,但我不明白为什么会出现错误。

"18:in ': undefined method %' for nil:NilClass (NoMethodError)"

我试了几个小时来解决这个问题,但似乎无法在网上找到解决方案... 我使用 Ruby 3.0.0,这是我到目前为止设法构建的代码:

nums = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
prime_nums = []
i = 0

#Loop on the array to check each element
while i <= nums.length
  check = 0
  divider = nums[i]

  #While to prevent DivisionByZero error
  while divider != 0
    if nums[i] % divider == 0    #/!\ ERROR HERE
      check += 1
    end
    divider -= 1
  end
  #Only division by 1 and itself will increment $check
  if check == 2
    prime_nums.append(nums[i])
  end
  i += 1
end
puts prime_nums

在您的示例中,这意味着 nums[i] returns 为零,因此情况是 i 大于 19。

您可以将 while i <= nums.length 更改为 while i < nums.length,因为数组在 Ruby 中从 0 开始索引。

undefined method %' for nil:NilClass 表示您正尝试在 nil 上使用 %nil 是当您尝试从数组中获取过多信息时得到的结果。

如果我们将 p "#{i}: #{nums[i]}" 放入循环中,我们将看到 i 变为 20。数组从 0 开始计数,因此如果数组中有 20 个元素,则最高索引为 19 . num[20]nil.

您可以通过 while i < nums.length 解决此问题以在 19 停止。

然而,很少有人在 Ruby 中编写 while 循环。相反,您使用方法进行迭代。 each iterates through each element of an Array. And you can count down with downto.

nums.each do |num|
  check = 0

  num.downto(1) do |divider|
    if num % divider == 0
      check += 1
    end
  end

  #Only division by 1 and itself will increment $check
  if check == 2
    prime_nums.append(num)
  end
end

现在没有机会差一分了。

@Schwern 的回答对在 Ruby 中使用迭代方法提出了很好的建议。我们可以使用它们来提高您的算法的效率。

def is_prime?(num)
  2.upto Math::sqrt(num) do |divisor|
    return false if num % divisor == 0
  end

  true
end

我们可以从 2 开始计算 num 的平方根,而不是从 num 向下迭代到 1 并跟踪除数。如果我们找到一个偶数除数,我们就知道它不是素数,并且可以立即 return false,省去了我们进一步迭代任何东西的努力。

如果我们到达循环的末尾,我们知道 num 必须是质数并且 return true.

然后假设我们要打印从 1500 的素数,我们可以这样做:

1.upto 500 do |num|
  puts num if is_prime? num
end