Function 将递归函数转化为尾部递归

Function 将递归函数转化为尾部递归,function,recursion,tail-recursion,ats,Function,Recursion,Tail Recursion,Ats,我正在用自动测试系统(ATS)进行编码,并试图生成一个函数,用于查找给定整数的平方根。这里提供的代码正确地满足了我的要求,但不是尾部递归 implement intsqrt(n) = if(n >= 1) then let val n4 = n / 4 val res = 2 * intsqrt(n4) + 1 in if(res * res <= n) then res else 2*intsqrt(n4) end else n 实现in

我正在用自动测试系统(ATS)进行编码,并试图生成一个函数,用于查找给定整数的平方根。这里提供的代码正确地满足了我的要求,但不是尾部递归

implement intsqrt(n) = 
if(n >= 1)
  then let
    val n4 = n / 4
    val res = 2 * intsqrt(n4) + 1
  in
    if(res * res <= n) then res else 2*intsqrt(n4)
  end
  else n
实现intsqrt(n)=
如果(n>=1)
那就让我
val n4=n/4
val res=2*intsqrt(n4)+1
在里面
如果(模式匹配“伪代码”中的res*res(Haskell,其中
是列表构建
cons
[]
是空列表),那么您的函数是

isqrt n | n<1=n

|res*res做这类事情的系统方法是通过CPS转换。 以下实现的特殊之处在于,在调用intsqrt_cps期间分配的每个内存字节在调用返回后都会被释放。 这里没有GC(与上述Haskell解决方案不同):


你确定你的算法正确吗?我把它翻译成Scheme,它适用于4和16,但不适用于9和25,除非我在翻译过程中出错。@据我所知,使用LPA是的。这是一个赋值,提示是“对于每个n>=1,让n4=n/4。然后sqrt(n)=2*sqrt(n4)或sqrt(n)=2*sqrt(n4)+1。”即使它可能不适用于所有数字,你有没有看到任何实用的方法将其转化为尾部递归?@uselpa我得到了3。据我所知,它的工作原理完全正确。这更多的是关于如何构造我的代码,而不是任何东西。关于尾部递归:查看所谓的“累积参数”。我发现了我的错误(
n/4
是ATS中的整数除法)。我认为您不能以尾部递归的方式实现这一点。您确定可以做到吗?
fun
intsqrt_cps
(
  n: int, k: int -<lincloptr1> int
) : int =
if
(n >= 1)
then let
  val n4 = n / 4
in
//
intsqrt_cps
( n4
, llam(res) =>
  applin(k, if square(2*res+1) <= n then 2*res+1 else 2*res)
) (* intsqrt_cps *)
//
end // end of [then]
else applin(k, 0) // end of [else]

fun intsqrt(n:int): int = intsqrt_cps(n, llam(x) => x)
==28857== Memcheck, a memory error detector
==28857== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==28857== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==28857== Command: ./intsqrt_cps.exe
==28857==
intsqrt(1023) = 31
intsqrt(1024) = 32
==28857==
==28857== HEAP SUMMARY:
==28857==     in use at exit: 0 bytes in 0 blocks
==28857==   total heap usage: 14 allocs, 14 frees, 1,304 bytes allocated
==28857==
==28857== All heap blocks were freed -- no leaks are possible
==28857==
==28857== For counts of detected and suppressed errors, rerun with: -v
==28857== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)