3

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

4

1 回答 1

5

问题是你评估@number了两次。并且修改也可能发生两次。

让我们看看数字为 2 时的情况:

@number = self.half if @number.even?

2 是偶数,所以减半。@number现在是 1。

但随后,第二行执行。

@number = self.triple_plus_one if @number.odd?

@number现在是奇数,所以变成 3*1 + 1。你看,poor@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
于 2013-11-05T20:21:17.353 回答