Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Ruby/Rails中的sum或reduce(:+;)更好吗?除了速度,还有其他考虑吗?_Ruby On Rails_Ruby - Fatal编程技术网

Ruby on rails Ruby/Rails中的sum或reduce(:+;)更好吗?除了速度,还有其他考虑吗?

Ruby on rails Ruby/Rails中的sum或reduce(:+;)更好吗?除了速度,还有其他考虑吗?,ruby-on-rails,ruby,Ruby On Rails,Ruby,对于长数组来说#sum比#reduce快,而对于短数组来说基本上是一样的 def reduce_t(s,f) start = Time.now puts (s..f).reduce(:+) #Printing the result just to make sure something is happening. finish = Time.now puts finish - start end def sum_t(s,f) start = Time.now puts (

对于长数组来说#sum比#reduce快,而对于短数组来说基本上是一样的

def reduce_t(s,f)
  start = Time.now
  puts (s..f).reduce(:+) #Printing the result just to make sure something is happening.
  finish = Time.now
  puts finish - start
end
def sum_t(s,f)
  start = Time.now
  puts (s..f).sum
  finish = Time.now
  puts finish - start
end

irb(main):078:0> sum_t(1,10); reduce_t(1,10)
55
0.000445
55
0.000195
=> nil
irb(main):079:0> sum_t(1,1000000); reduce_t(1,1000000)
500000500000
8.1e-05
500000500000
0.101487
=> nil
除了速度,还有其他考虑吗?有没有哪种情况下,用“减少”而不是“求和”来达到同样的目的,一个简单的求和会更好

编辑

正确地指出,在得出关于计时结果的结论之前,我应该进行多次迭代。我没有使用
基准测试
,因为我还不熟悉它,但我希望我下面所写的内容将是充分和令人信服的

def sum_reduce_t(s,f)
  time_reduce = 0
  time_sum = 0
  reduce_faster = 0
  sum_faster = 0
  30.times do
    start_reduce = Time.now
    (s..f).reduce(:+)
    finish_reduce = Time.now
    time_reduce += (finish_reduce - start_reduce)
    start_sum = Time.now
    (s..f).sum
    finish_sum = Time.now
    time_sum += (finish_sum - start_sum)
    if time_sum > time_reduce
      reduce_faster += 1
    else
      sum_faster += 1
    end
  end
  puts "Total time (s) spent on reduce: #{time_reduce}"
  puts "Total time (s) spent on sum: #{time_sum}"
  puts "Number of times reduce is faster: #{reduce_faster}"
  puts "Number of times sum is faster: #{sum_faster}"
end

irb(main):205:0> sum_reduce_t(1,10)
Total time (s) spent on reduce: 0.00023900000000000004
Total time (s) spent on sum: 0.00015400000000000003
Number of times reduce is faster: 0
Number of times sum is faster: 30
=> nil
irb(main):206:0> sum_reduce_t(1,100)
Total time (s) spent on reduce: 0.0011480000000000004
Total time (s) spent on sum: 0.00024999999999999995
Number of times reduce is faster: 0
Number of times sum is faster: 30
=> nil
irb(main):207:0> sum_reduce_t(1,1000)
Total time (s) spent on reduce: 0.004804000000000001
Total time (s) spent on sum: 0.00019899999999999996
Number of times reduce is faster: 0
Number of times sum is faster: 30
=> nil
irb(main):208:0> sum_reduce_t(1,10000)
Total time (s) spent on reduce: 0.031862
Total time (s) spent on sum: 0.00010299999999999996
Number of times reduce is faster: 0
Number of times sum is faster: 30
=> nil
irb(main):209:0> sum_reduce_t(1,100000)
Total time (s) spent on reduce: 0.286317
Total time (s) spent on sum: 0.00013199999999999998
Number of times reduce is faster: 0
Number of times sum is faster: 30
=> nil
irb(main):210:0> sum_reduce_t(1,1000000)
Total time (s) spent on reduce: 2.7116779999999996
Total time (s) spent on sum: 0.00021200000000000008
Number of times reduce is faster: 0
Number of times sum is faster: 30
=> nil    

我的问题仍然是:有没有使用“减少”而不是“求和”的时候是有意义的?

好的,我认为这些评论可以结合起来形成一个好的答案,不过如果有人想更深入地解释,我当然会接受其他人

重点是:

  • sum方法在当前版本的Ruby中不可用,但在将来可以使用。我是通过Rails使用它的,在Rails可用的地方
  • 求和法对大型数组求和确实更快
  • 将旧代码从reduce改为sum可能不值得,除非存在与超长数组相关的性能问题
  • “考虑到数组的#和是,它的速度应该不会太快。”
  • Reduce做了很多其他的事情(
    Reduce(:-)
    Reduce(:*)
    ,等等),所以它不应该被认为是无用的。如果sum方法可用,那么它就不是求和一个巨大数组的最佳选择
  • 我认为,最重要的一点是:如果您需要代码与Ruby的早期版本兼容,reduce更安全
  • “当您添加许多小值时,总和确实会增加,这在inject&:+中不会发生。”(@matt)
  • reduce方法可以生成一些有趣的表情
我的问题的直接答案是:

  • 除了速度,还有其他考虑吗(兼容性,将非常大的数字添加到非常小的数字中)
  • 是否存在使用#reduce更好的情况 不是为了达到同样的目的而求和,而是简单的求和 (兼容性)

使用
sum
的行为和结果与
inject&:+
不同的一种方式是对浮点值求和

如果将大的浮点值添加到小的浮点值,结果通常与大的浮点值相同:

> 99999999999999.98 + 0.001
=> 99999999999999.98
这可能会导致在添加浮点数组时出错,因为较小的值实际上会丢失,即使有很多值

例如:

> a = [99999999999999.98, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001]
=> [99999999999999.98, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001]
> a.inject(&:+)
=> 99999999999999.98
在本例中,您可以根据需要随时添加
0.001
,它永远不会更改结果的值

使用“求和浮点数时”可减少此错误:

> a.sum
=> 100000000000000.0

(请注意这里的结果,您可能希望数组中有10个
0.001
的值以
.99
结尾。这只是正常的浮点行为,也许我应该尝试找到一个更好的示例。重要的一点是,当您添加大量小值时,总和确实会增加,而
inject&::+

@AndreyDeineko它在ruby 2.4.Wohoo!中。(1)您需要进行多次迭代才能获得任何有用的计时结果,也许您应该使用标准库中的
基准测试
,而不是自己滚动。(2)鉴于此,速度更快也就不足为奇了。@Anthony,这应该是一个惊喜。Leo,你应该添加一个Rail标签,因为Ruby v2.4.0还没有发布。我的意思是……这是个问题吗?这似乎是一种毫无意义的优化;任何一种都是线性时间运行的。Leo,我在v2.3.0和
[1,2,3].sum#=>NoMethodError:[1,2,3]:数组的未定义方法“sum”
。我希望执行速度的差异不会达到。哪一个更优雅?你告诉我。很好的总结!你还可以添加@matt关于sum改进浮点行为的解释吗?