Ruby中的变量分配是否真的很贵,还是优化了链式字符串方法?

时间:2011-05-04 16:01:04

标签: ruby string performance

我为Project Euler - Problem 36编写了以下方法。所有这一切都是将基数10和基数2中所有小于1,000,000的数字加起来。

def problem_36
  (1...1_000_000).select do |n|
    n.to_s == n.to_s.reverse && n.to_s(2) == n.to_s(2).reverse
  end
end

现在,这可以工作,并在1秒钟内给出正确的结果。我希望在1秒内得到它,所以我决定减少将数字转换为字符串的次数。所以我做了以下更改:

def problem_36
  (1...1_000_000).select do |n|
    base10 = n.to_s
    base2  = n.to_s(2)
    base10 == base10.reverse && base2 == base2.reverse
  end
end

问题是,这个版本实际上比原来的版本运行了大约50%。所以问题是:分配这两个变量真的很慢吗?或者Ruby是否优化链式方法调用?

2 个答案:

答案 0 :(得分:7)

在这一行

n.to_s == n.to_s.reverse && n.to_s(2) == n.to_s(2).reverse

如果第一部分是false(Ruby的&&运算符短路,unlike its & counterpart),则不执行第二部分。这节省了很多对to_s(2)的调用。

答案 1 :(得分:0)

有趣。

通常的Ruby性能规则是,如果程序使用内置操作,它将会很快。如果没有,那就会很慢。

即使您的第二个版本可能会或可能不会执行更少的转换,但它会执行三个Ruby行与一个。

我曾经读过一个大型日志文件。在我的第一个版本中,我使用Ruby代码保留了一个有效的行链表。

1。时间复杂度:O(1)。

然后我将其更改为仅使用<<并将每个新节点添加到数组的末尾。

2. 时间复杂度:O(N 2 ),或至少为O(N 1 +ε

第二个版本(1)更快。


1。显然,实现是将数组扩展为块,因此它不是完全二次的,但仍然比链表更多的工作。