首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >fibonacci cps实现

fibonacci cps实现
EN

Stack Overflow用户
提问于 2022-09-18 16:51:02
回答 2查看 126关注 0票数 1

我试图将不同的函数从尾递归转换为cps (延续传递样式)。

我设法完成了一个求和和阶乘函数:

和函数:

尾递归:

代码语言:javascript
复制
let sum n =
  let rec subSum n acc =
    match n with
    |0 -> acc
    |_ -> subSum (n-1) (n+acc)
  in subSum n 0;;

Printf.printf "%u\n" (sum 5);; (*returns 15*)

cps版本:

代码语言:javascript
复制
let sum2 n =
  let rec sum_cps n acc =
    match n with
    |0 -> acc 0
    |_ -> sum_cps (n-1) (fun r -> acc (n+r))
  in sum_cps n (fun n -> n);;

Printf.printf "%u\n" (sum2 5);; (*returns 15*)

阶乘(与和相同的风格):

尾递归:

代码语言:javascript
复制
let fact n =
  let rec subFact n acc =
    match n with
    |0 -> acc
    |1 -> acc
    |_ -> subFact (n-1) (n*acc)
  in subFact n 1;;

Printf.printf "%u\n" (fact 6);; (*returns 720*)

cps版本:

代码语言:javascript
复制
let fact2 n =
  let rec fact_cps n acc =
    match n with
    |0 -> acc 1
    |1 -> acc 1
    |_ -> fact_cps (n-1) (fun r -> acc (n*r))
  in fact_cps n (fun n -> n);;

Printf.printf "%u\n" (fact2 6);; (*returns 720*)

然而,在fibonacci中,除了累加器之外还有另一个论点,这使我感到有点不安:

尾递归版本:

代码语言:javascript
复制
let fibo n =
  let rec fibon n acc prev =
    match n with
    |0 -> acc
    |_ -> fibon (n-1) (prev+acc) acc
  in fibon n 0 1;;

Printf.printf "%u\n" (fibo 6);; (*returns 8*)

cps尝试(不起作用):

代码语言:javascript
复制
let fibo n =
  let rec fibo_cps n acc prev =
    match n with
    |0 -> 0
    |_ -> fibo_cps (n-1) (fun r -> acc (prev+r)) acc
  in fibo_cps n (fun n -> n) 1;;

对这个问题的解释:

有问题的线路(根据解释性者):

代码语言:javascript
复制
|_ -> fibo_cps (n-1) (fun r -> acc (prev+r)) acc

错误信息:

代码语言:javascript
复制
Line 5, characters 49-52: Error: This expression has type int -> 'a but an expression was expected of type int

我只想了解如何使fibonacci的cps版本工作。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-09-18 17:13:35

我想这就是你要找的-

代码语言:javascript
复制
let fibo n =
  let rec fibo_cps n acc =
    match n with
    |0 -> acc 0
    |1 -> acc 1
    |_ -> fibo_cps (n-1) (fun x -> fibo_cps (n-2) (fun y -> acc (x+y)))
  in fibo_cps n (fun x -> x)

请注意,虽然上面的计算是尾递归的,但计算斐波纳契数的方法仍然非常低效。考虑一个线性迭代算法-

代码语言:javascript
复制
let fibo2 n =
  let rec aux n a b =
    match n with
    |0 -> a 
    |_ -> aux (n-1) b (a+b)
  in aux n 0 1
票数 2
EN

Stack Overflow用户

发布于 2022-09-18 18:28:01

将尾递归版本直接转换为cps样式的方法如下

代码语言:javascript
复制
let rec fib_cps n k =
  if n <= 1 then k
  else fib_cps (n-1) (fun (prev,n) -> k (n, prev+n))
let fib n = snd @@ fib_cps n Fun.id (0,1)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73764692

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档