Haskell 如何存储和引用递归函数的中间值
在过去的几周里,我刚刚开始学习Haskell。我正在使用项目Euler问题来学习,目前正在尝试找出是否有可能。不是找人给我答案,只是需要帮助理解Haskell中的数据结构 我目前正在研究,它指定了一个递归函数。编写函数不是问题,我目前有:Haskell 如何存储和引用递归函数的中间值,haskell,recursion,Haskell,Recursion,在过去的几周里,我刚刚开始学习Haskell。我正在使用项目Euler问题来学习,目前正在尝试找出是否有可能。不是找人给我答案,只是需要帮助理解Haskell中的数据结构 我目前正在研究,它指定了一个递归函数。编写函数不是问题,我目前有: import Math.NumberTheory.Primes import Data.Maybe import Data.List derivative :: Integer -> Integer derivative x | x <
import Math.NumberTheory.Primes
import Data.Maybe
import Data.List
derivative :: Integer -> Integer
derivative x
| x < 2 = error "Error: Attempt to evaluate outside domain"
| isPrime x = 1
| otherwise = (derivative a)*b + a*(derivative b)
where
[a, b] = int_split x
--this function find the first pair of divisors
int_split :: Integer -> [Integer]
int_split n = [first_div, n `div` first_div] where
first_div = fromJust $ find (\x -> (n `mod` x) ==0) [2..]
导入Math.NumberTheory.Primes
导入数据,也许吧
导入数据。列表
导数::整数->整数
导数x
|x<2=错误“错误:尝试在域外求值”
|iPrime x=1
|否则=(导数a)*b+a*(导数b)
哪里
[a,b]=整数分割x
--此函数用于查找第一对除数
int_split::Integer->[Integer]
int_split n=[first_div,n`div`first_div]其中
first_div=fromJust$find(\x->(n`mod`x)==0)[2..]
由于计算结果与问题给出的样本值相匹配,这似乎工作得很好。问题是我需要计算非常大的值,通过5x10^15获得所有值。将所有值设置为~10^8运行得非常快,但如果超过此值,则运行得非常慢。简单地使用map肯定是低效的,因为它没有利用我们可以引用以前计算的值这一事实
我的想法是将我的函数更改为将值存储在查找表中,因为这些值是计算出来的,函数可以引用。我尝试使用Data.Map来存储值,但我不知道如何以递归方式将其集成到函数中。这在哈斯克尔可能吗?还是有一种我没有想到的更好的方法来存储和使用中间计算 我真的不认为优化您当前的方法可以在合理的时间内得到您想要的答案。假设您优化得非常好,可以在一个时钟周期内计算出任意数字的解,我们给您一个相对正常的3GHz处理器
$ units
You have: 3 giga hertz
You want: / day
* 2.592e+14
/ 3.8580247e-15
即使以如此快的速度,您每天也只能解决2.5e14个输入。因此,计算5e15之前的解需要6天时间。但当然,即使是算法的最佳优化也无法让你接近这个速度。与Project Euler问题的常见情况一样,在使用计算机解决问题之前,您必须先做一些更复杂的数学运算来缩小问题的大小。查找“记忆”,您应该可以找到几个示例。感谢您的建议,只是不知道要查找什么!我的数学背景比较好,所以我对其中一些概念有点不熟悉。我认为你是对的。我找到了一种方法,根据它的素因子分解重写函数,这可能会加快速度。我主要关心的是存储值的想法,而另一条关于“记忆化”的评论似乎也提到了这一点。