为什么会导致无限循环?

时间:2013-11-05 20:17:30

标签: ruby

我有一个简单的程序,我想要一个数字,并迭代地应用两个规则之一,将数字降低到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之间交替。这是怎么回事?谢谢!

1 个答案:

答案 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
相关问题