Haskell 中的整数时间复杂度

发布于 2024-09-25 10:28:13 字数 583 浏览 4 评论 0原文

上周我在学校接到了一项作业,要实现一个计算斐波那契数列中第 n 个数字的函数。 “子作业”是使用累加来实现它(可能不是正确的翻译),以便为函数提供 O(n) 时间复杂度。这一切都工作得很好,直到我尝试创建该函数(Int -> Integer)。通过一些实验,我意识到对于非常大的数字,时间复杂度接近 O(n^2)。 我觉得这一定是因为 Integer 实现的原因,这让我有点好奇它是如何工作的。我做了一些谷歌搜索,但没有找到任何看起来有用的东西,所以我向你们求助,希望得到一个解释或一个彻底解释它的链接。

我的代码:

ackfib 0 = 0
ackfib 1 = 1        
ackfib n = loop n 1 0 1
    where
        loop n n1 n2 i 
            | i < n     = loop n (n1+n2) n1 (i+1)
            | i == n    = n1
            | i > n     = error "n must be greater than or equal to 0"

我感谢

Viktor 的所有回答

I had an assignment in school last week to implement a function for calculating the n:th number in the fibonacci sequence. A 'sub-assignment' was to implement it using accumulation(Might not be a correct translation) in order to give the function O(n) time complexity. This all worked fine until I tried making the function (Int -> Integer). By experimenting a bit I realised that the time complexity was close to O(n^2) for really large numbers.
It occurs to me that this must be because of the Integer implementation, which makes me a bit curious about how it works. I did a few Google searches and didn't find anything that seemed useful so I am turning to you guys in hope of either getting an explanation or a link that explains it thoroughly.

My code:

ackfib 0 = 0
ackfib 1 = 1        
ackfib n = loop n 1 0 1
    where
        loop n n1 n2 i 
            | i < n     = loop n (n1+n2) n1 (i+1)
            | i == n    = n1
            | i > n     = error "n must be greater than or equal to 0"

I am thankful for all answers

Viktor

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

荒芜了季节 2024-10-02 10:28:13

这实际上与 Haskell 无关,这只是斐波那契数快速呈指数增长这一事实的结果。具体来说,第 n 个斐波那契数大约有 (log2 φ) n 或大约 0.48 n 位,其中 φ 是黄金比例 (1 + sqrt 5) / 2。由于 k 位整数的加法需要 O (k) 时间,您的 O(n) 加法实际上总共需要 O(n^2) 时间,因为平均而言您要添加的数字有 O(n) 位。

(坚持者请注意:上面的大 O 应该是大 Theta。)

This has nothing to do with Haskell really, it's just a result of the fact that the Fibonacci numbers grow exponentially quickly. Specifically, the nth Fibonacci number has about (log2 φ) n or roughly 0.48 n bits where φ is the golden ratio (1 + sqrt 5) / 2. Since addition of k-bit integers takes O(k) time, your O(n) additions actually take a total of O(n^2) time, because on average the numbers you're adding have O(n) bits.

(Note for sticklers: big O should really be big Theta in the above.)

故人如初 2024-10-02 10:28:13

要添加到 Reid 的答案,您的算法具有 O( N)时间复杂度取决于您认为执行的步骤。这是对时间复杂度的一个常见误解:时间复杂度始终与执行时间相对应。

考虑什么步骤取决于我们想要分析问题的深度。如果您将一个步骤定义为整数的一次加法,是的,您的带有累加器的算法将在 O(N) 时间内运行。如果将一个步骤定义为单字加法(32 位或 64 位加法),则其运行时间为 O(N^2),正如 Reid 所解释的那样。

如果您希望复杂性分析与执行时间相对应,则需要使用执行时间受常量限制的执行步骤,例如两个处理器字的相加。整数的加法则不然,因为整数可以任意大。

To add to Reid's answer, the fact that your algorithm has O(N) time complexity depends on what you consider to be the step of execution. This is a common misconception of time complexity: that time complexity always corresponds to execution time.

What to consider the step depends on how deep we want to analyse the issue. If you define a step as one addition of Integer, yes, your algorithm with accumulators runs in O(N) time. If you define a step as one word addition (a 32- or 64-bit addition), it runs in O(N^2) as Reid explained.

If you want your complexity analysis to correspond to the execution time you need to use a step of execution whose execution time is bounded above by a constant, like the addition of two processor words. Addition of Integers is not, because Integers can be arbitrarily large.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文