代码之家  ›  专栏  ›  技术社区  ›  Robert Massaioli

Ruby数学函数记忆

  •  1
  • Robert Massaioli  · 技术社区  · 17 年前

    我编写了一些代码,如下所示:

    def get(x, y)
       @cachedResults.set(x,y, Math.hypot(x, y)) if @cachedResults.get(x,y).nil?
       @cachedResults.get(x,y)
    end
    

    def get(x, y)
       Math.hypot(x, y)
    end
    

    而且,令我惊讶的是,它只花了15秒就再次运行了。同一时间。所以我的问题是,ruby中的数学函数是自然记忆的吗?如果是这样,ruby的记忆化程度如何?

    (如果不是,那么你为什么认为我一直得到这个结果?)

    3 回复  |  直到 17 年前
        1
  •  4
  •   Pete Kirkham    17 年前

    为你做任何事情160000次需要15秒吗?在您的系统上测试它,只返回x;很可能是hypot操作(用C实现)比解释器开销可以忽略不计。

    对于ruby 1.8.7,使用khell的memonized get方法,在get方法内调用函数,在get方法内返回x,迭代次数为100000次:

    peregrino:$ time ruby src/memoized_hypot.rb 
    
    real    0m1.714s
    user    0m1.436s
    sys 0m0.080s
    peregrino:$ time ruby src/plain_hypot.rb 
    
    real    0m0.495s
    user    0m0.364s
    sys 0m0.060s
    peregrino:$ time ruby src/empty_hypo.rb 
    
    real    0m0.369s
    user    0m0.220s
    sys 0m0.068s
    

    调用hypot和仅返回x之间的差异表明hypot只占运行时的25%。这不是您应该优化的代码-如果可以,请尝试将调用内联到库中,而不是用另一种方法包装它。

    peregrino:$ time ruby src/inline_hypot.rb 
    
    real    0m0.365s
    user    0m0.236s
    sys 0m0.044s
    

    那是

    100000.times{ |i| Math.hypot(i,6) }   
    

    100000.times{ |i| foo.get(i,6) }   
    

    其中foo是一个方法已发布的对象。


        2
  •  3
  •   khelll    17 年前

    试试这个:

    def initialize
      @cachedResults = {}
    end
    
    def get(x, y)
       @cachedResults["#{x}:#{y}"] ||= Math.hypot(x, y)
    end
    
        3
  •  1
  •   pierrotlefou    17 年前

    我不指望这里的记忆力会提高 很多 在这种情况下。

    我所做的只是 sqrt(x**2 + y**2) . 它不是对已计算值的递归调用。

    推荐文章