我有一个简单的程序,我想要一个数字,并迭代地应用两个规则之一,将数字降低到1,同时跟踪到达那里需要多少次迭代。
规则很简单:(对于正整数n) n - > n / 2(n是偶数) n - > 3n + 1(n为奇数)
我写的代码是为了实现这个目标:
class Collatz
attr_accessor :number, :counter
def initialize(number)
@number = number
@counter = 0
end
def collatz
until (@number == 1) do
self.hotpo
@counter += 1
end
end
def hotpo
@number = self.half if @number.even?
@number = self.triple_plus_one if @number.odd?
end
def half
@number / 2
end
def triple_plus_one
(3 * @number) + 1
end
end
num = Collatz.new(13)
puts num.number #==> 13
puts num.counter #==> 0
num.collatz #currently results in infinite loop
puts num.number #should give 1
puts num.counter #should give 9
所以例如,如果我实例化对象,传入13,@ number应该从13改为 - > 40 - > 20 - > 10 - > 5 - > 16 - > 8 - > 4 - > 2 - > 1然后终止,但它目前陷入无限循环,在@ number = 2和@number = 4之间交替。这是怎么回事?谢谢!
答案 0 :(得分:5)
问题在于您评估@number
两次。修改也可能发生两次。
让我们看看数字为2时的情况:
@number = self.half if @number.even?
2是偶数,因此减半。 @number
现在为1。
但是,第二行执行。
@number = self.triple_plus_one if @number.odd?
@number
现在是奇数,所以它变成3 * 1 + 1.你看,差@number
永远不会稳定在1。
要解决此问题,您需要检查一次号码。然后进行一次修改。
def hotpo
if @number.even?
@number = half
else
@number = triple_plus_one
end
end
或更短的表格
def hotpo
@number = @number.even? ? half : triple_plus_one
end