ruby - 为什么这会导致无限循环?

标签 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 之间交替。这是怎么发生的?谢谢!

最佳答案

问题是你计算了两次@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

关于ruby - 为什么这会导致无限循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19798107/

相关文章:

ruby - 为什么 Ruby 1.9 lambda 调用不可能没有圆括号前面的点?

ruby - 纯 Ruby 并发哈希

Ruby 打印散列键和值

ruby-on-rails - 使用 Pow 作为服务器在 RubyMine 中调试 - Ruby 2.1.1 + Rails 4

ruby-on-rails - 安装 rvm 后路径损坏?

ruby - 在 Ruby 中声明变量?

ruby - 如何从 mongodb ruby​​ 驱动程序打印 JSON?

ruby - 设置 :linked_files and set :linked_files for uploads in capistrano3

ruby - 在 Ruby 中解析缩写数字

ruby-on-rails - Rails enumerables : why would find_all{. ..}.count 返回的值与 count{...} 不同?