【问题标题】:Memoization techniques记忆技术
【发布时间】:2014-05-03 14:05:41
【问题描述】:

在尝试一些记忆技术时,我偶然发现了这个基准测试结果,这与我的预期相反。似乎我犯了一些愚蠢的错误,有人看到我在这里做错了吗(基准对记忆和非记忆代码给出了相似的结果)?

require 'benchmark'

# -----------------------------------------

class FactorialClass

  @@sequence = [1]

  def self.of( n )
    @@sequence[n] || n * of( n - 1 )
  end

end

# -----------------------------------------

def factorial_with_memoization
  sequence = [1]
  lambda = Proc.new do |n|
    sequence[n] || n * lambda.call( n - 1 )
  end
end
f = factorial_with_memoization()

# -----------------------------------------

def factorial n
 n == 0 ? 1 : n * factorial( n - 1 )
end

# -----------------------------------------



count = 1_000
n = 1000

without_memoization = Benchmark.measure do
  count.times do 
    factorial(n)
  end
end

with_memoization_lambda = Benchmark.measure do
  count.times do 
    f.call(n)
  end
end

with_memoization_class = Benchmark.measure do
  count.times do 
    FactorialClass.of(n)
  end
end


puts "Without memoization           : #{ without_memoization }"
puts "With memoization using lambda : #{ with_memoization_lambda }"
puts "With memoization using class  : #{ with_memoization_class }"

** 结果是:**

Without memoization           :   1.210000   0.100000   1.310000 (  1.309675)
With memoization using lambda :   1.750000   0.100000   1.850000 (  1.858737)
With memoization using class  :   1.270000   0.090000   1.360000 (  1.358375)

【问题讨论】:

  • 我不认为你会记住任何东西......
  • 我相信缓存不起作用?你能解释一下什么是错的吗?
  • 对于 n 的阶乘,您最终会计算 n 阶乘。所以你不会记住任何东西。您永远不会“存储”任何结果。

标签: ruby memoization


【解决方案1】:

您永远不会将任何记忆值分配给缓存。正如@xlembouras 所说,你什么都没记住。

class FactorialClass
  @@sequence = [1]

  def self.of( n )
    # @@sequence[n] get evaluated to nil unless n is 0, always!
    @@sequence[n] || n * of( n - 1 )
  end
end

完成计算后,您需要手动将记忆值分配给缓存。

class FactorialClass
  @@sequence = [1]

  def self.of( n )
    @@sequence[n] = (@@sequence[n] || n * of( n - 1 ))
  end
end

但是,记忆真的适用于您的阶乘计算吗?没有。

f(n) = n * f(n-1) = n * ((n-1) * f(n-2)) = ... = n * ((n-1) * (... * (3 * f(2))))

所有的递归步骤都会计算一个新值(从 2 到 n)的阶乘,这是以前没有计算过的。记忆不会在任何步骤中受到打击。

【讨论】:

  • 没错,如果你想尝试记忆,去斐波那契。
  • 太傻了,我错过了不是"||=";在查看代码时,我一直在阅读 ||作为||=,仍然不知道我是怎么错过的。伤心。
猜你喜欢
  • 1970-01-01
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 2020-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-11
相关资源
最近更新 更多