这是一个来自教科书的程序:
# Initialize our counter
i = 1
# i: [0, 100]
while (i <= 100)
# Initialize prime flag
prime_flag = true
j = 2
# Test divisibility of i from [0, i/2]
while (j <= i / 2)
# puts " i ==> " to i.to_s + " j ==> " + j.to_s
if (i % j == 0)
prime_flag = false
# break
end
j = j + 1
end
# We found a prime!
if prime_flag
puts "Prime ==> " + i.to_s
end
# Increment the counter
i += 1
end
while (j <= i / 2)
引入了一个新循环。如果我们试图找到素数怎么办?这是为什么写的?素数不具有平方根。 j
<= i / 2
的目的是什么?我不明白为什么会引入j
。
答案 0 :(得分:1)
你是对的,你应该只检查numbers <= floor(sqrt(i))
。上述代码不必要地检查ceil(sqrt(i))
到i/2
的数字。然而,它会给出正确的答案。
此外,这不是类似Ruby的代码。这太糟糕了,作者应该觉得很糟糕(除非他们打算向你展示一些不好的东西,以便当你看到如何更好地写出它时让你感到惊讶!)。
这里的代码是以类似Ruby的方式完成的。请注意,prime?
绝对可以是一个单行,但我在问题的上下文中分解了更多行的可读性:
def prime?(i) # Define a function that takes 1 parameter `i`
MAX_NUM_TO_CHECK = Math.sqrt(i) # No need to check numbers greater than sqrt(i)
(2..MAX_NUM_TO_CHECK).all? do |j| # Return `true` if the following line is true for
# all numbers [2,MAX_NUM_TO_CHECK]
i % j != 0 # true if `i` is evenly not divisible by `j`. Any
# input that evaluates to false here is not prime.
end
end
# Test primality of numbers [1,100]
(1..100).each {|n| puts "Prime ==> #{n}" if prime? n}
我认为您的图书与此代码之间的最大区别是:
<= sqrt(i)
。一旦我们知道一个数字不是素数,我们也会停止检查。(1..100)
。这对我来说似乎是一个很好的功能划分,有助于提高可读性。 此处使用的某些语言功能不在您的示例中:
if
之后的事物)求值为true时才计算表达式。这可以使一些陈述更具可读性。(x..y)
,允许您快速描述一系列值,您可以在不保留计数器的情况下迭代这些值。内部代码
do |param1, ..., paramN| <CODE>; end
或
{|param1, ..., paramN| <CODE>}
称为block
。它是一个匿名函数(作为参数传递给另一个函数/方法的函数)。我们在all?
和each
处使用此功能。
each
用于在集合的每个元素上运行代码块,忽略返回值all?
可用于确定某个块是否为集合中的每个项目返回true
。如果您不熟悉将代码传递给函数,这可能有点令人困惑。它允许您根据需要执行不同的代码。例如,each
为集合中的每个项运行生成的块。您可以在该块中执行任何操作而不更改each
的定义...您只需将其生成块并运行该块用适当的参数。 Here is a good blog post to get you started on how this works and what else you can use it for。