【问题标题】:For loop... ForeverFor循环...永远
【发布时间】:2015-10-12 12:50:32
【问题描述】:

我有一个 for 循环,我希望它永远递增。

我的代码:

for a in (0...Float::INFINITY).step(2)
    puts a
end

输出:

0.0
2.0
4.0
Etc. Always with "#{a}.0"

有没有什么办法可以将无穷大表示为整数,这样输出的末尾就没有.0,而不会对循环的内容进行任何操作?

附录

您能否解释一下您的循环是如何工作的?我正在尝试找到最有效的解决方案,因为由于这个循环将无限迭代,因此减少几毫秒将大大提高性能。

还有……

我会接受以最短时间运行到 1000000 的解决方案

根据 benchmark@Sefan 和 while 循环答案花费相同的时间Fruity while 循环答案需要更短的时间,for在第二个循环答案,但多个loop do 答案需要更长的时间。

由于原因超出了这个问题的范围,我创建了另一个问题来解决为什么某些循环比其他循环更快 (https://stackoverflow.com/questions/33088764/peddle-to-the-metal-faster-loop-faster)。

【问题讨论】:

  • “[S]因为这个循环将无限迭代,所以减少几毫秒将大大提高性能”——我不明白。一个无限的过程永远不会结束。每次迭代的性能差异不会产生任何影响。
  • @sawa 这是我的代码的一个非常简化的版本,我正在尝试检查循环达到的每个数字是否具有特定特征,并且我希望循环尽快检查数字。因此,如果检查每个数字所需的时间减少一毫秒,那么在检查 100 万个数字后,它将节省一秒,它将检查数万亿个数字。
  • @sawa 它将在某个时候终止。没有实际运行无限循环的循环,因为出于所有意图和目的,任何无限循环都将被终止。
  • @shivam 的答案是一个 while 循环,因此您的更新没有多大意义。至于 Stefan 的回答,我在回答中解释了其中的原因。
  • @engineersmnky 对不起!我不是说while 循环答案,我的意思是loop do 答案。现在编辑。感谢您了解这一点。

标签: ruby loops optimization


【解决方案1】:

您可以使用Numeric#step 而不超过限制

0.step(by: 2) { |i| puts i }

输出:

0
2
4
6
...

你也可以建立自己的Enumerator:

step2 = Enumerator.new do |y|
  a = 0
  loop do
    y << a
    a += 2
  end
end

step2.each { |i| puts i }

【讨论】:

  • @thesecretmaster 你可以写for i in 0.step(by: 2)
  • 在 Ruby 2.0 的 Numeric#step987654322@ 中有任何简单的方法吗?
  • @WandMaker 你可以使用Integer#upto 代替例如0.upto(Float::INFINITY) { |i| puts i * 2} 这将具有与使用 Numeric#step 相同的输出,如果您使用 Float::INFINITY 作为限制,则将导致值转换为 Floats。要么创建自己的Enumerator,在这种情况下也很容易。
  • @WandMaker 我添加了一个带有自定义Enumerator的示例
【解决方案2】:

您可以为此使用while true

puts a = 0
puts a+=2 while true

顺便说一句,

有没有办法用整数表示无穷大

【讨论】:

  • 这个循环会在每次迭代后检查true == true吗?
  • 每次迭代后它会检查条件是否为true - YES。它是否通过true == true 进行检查? - 没有。
  • 输出以2开头,即省略0
  • 打印0 同时分配解决了这个问题。虽然不是一个聪明的解决方案。
  • 或许a = -2; puts a+= 2 while true
【解决方案3】:
require 'bigdecimal'
(0..BigDecimal('Infinity')).step(2).each{ |n| puts n }

require 'bigdecimal'
for a in (0...BigDecimal::INFINITY).step(2)
  puts a
end

【讨论】:

    【解决方案4】:

    这就是循环方法的设计目的。 loop 没有运行条件。它将无限期地运行,退出的唯一方法是使用关键字break。 (或提出StopIteration

    a = 0
    loop { puts a += 2} 
    

    这个循环将是无限的,因为没有指定break

    break 的指定方式与其他答案在需要时使用 while 条件的方式非常相似:

    a = 0 
    loop do 
      puts a += 2
      break if a > 1_000_000
    end
    

    一旦a 的值超过 1M,这个loop 现在将退出。

    话虽如此,@Stefan 的答案更有效,因为它不存储这个整数值或必须执行任何额外的赋值,而是简单地从枚举器中产生数字并在之后丢弃它。这样做的用处更多地取决于您对该循环的实现和目的。

    【讨论】:

    • loop 不是关键字,它只是一种方法。
    • @JörgWMittag 我很抱歉将答案修改为 “循环方法”
    【解决方案5】:

    试试这个:

    arr = [0]
    arr.cycle(1000000) { |i| puts arr[0] +=2  }
    

    如果你想要无限循环,那么,不要将任何参数传递给cycle

    arr = [0]
    arr.cycle { |i| puts arr[0] +=2  }
    

    【讨论】:

      【解决方案6】:
      a = [-2]
      puts a.unshift(a.shift+2) while 'loop forever'
      

      【讨论】:

        猜你喜欢
        • 2014-11-23
        • 1970-01-01
        • 1970-01-01
        • 2014-08-04
        • 1970-01-01
        • 1970-01-01
        • 2014-05-30
        • 2020-09-11
        • 2017-10-28
        相关资源
        最近更新 更多