Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中双阶乘方程的尾部递归_C_Tail Recursion - Fatal编程技术网

C中双阶乘方程的尾部递归

C中双阶乘方程的尾部递归,c,tail-recursion,C,Tail Recursion,我很难实现以下问题的尾部递归解决方案: 双阶乘还有另一个递归关系,它也依赖于阶乘,如上所述:(对于n,这里是阶乘函数的尾部递归版本: long factorial(int n, int factor) { if (n == 0) return factor; return factorial(n-1, factor * n); } factorial(5, 1); // 120 unsigned long long doublefactorial(int n

我很难实现以下问题的尾部递归解决方案:


双阶乘还有另一个递归关系,它也依赖于阶乘,如上所述:(对于n,这里是阶乘函数的尾部递归版本:

long factorial(int n, int factor)
{
    if (n == 0)
        return factor;

    return factorial(n-1, factor * n);
}

factorial(5, 1); // 120
unsigned long long doublefactorial(int n) {
    if (n < 0)
        return 0;
    if (n < 2)
        return 1;
    return n * doublefactorial(n - 2);
}
unsigned long long doublefactorial_helper(int n, unsigned long long res) {
    if (n < 2)
        return res;
    return doublefactorial(n - 2, res * n);
}

unsigned long long doublefactorial(int n) {
    return doublefactorial_helper(n, n >= 0);
}
下面是一个具有更简单逻辑的尾部递归双阶乘:

long doublefactorial(int n, int factor)
{
    if (n < 0)
        return 0;
    if (n < 2)
        return factor;

    return doublefactorial(n-2, factor * n);
}

printf("%d ", doublefactorial(5,1)); // 15
printf("%d ", doublefactorial(10,1)); // 3840
printf("%d ", doublefactorial(18,1)); // 185794560 
长双阶乘(整数n,整数因子)
{
if(n<0)
返回0;
if(n<2)
回报系数;
返回双因子(n-2,因子*n);
}
printf(“%d”,双阶乘(5,1));//15
printf(“%d”,双阶乘(10,1));//3840
printf(“%d”,双阶乘(18,1));//185794560
您对该函数的定义不完整:您需要一个初始值,例如0!!=1。从递归定义来看,p!!似乎是从1到p的所有数字的乘积,这些数字与p具有相同的奇偶校验:

long long factorial(int n) {
    if (n < 0)
        return 0;
    if (n < 1)
        return 1;

     return n * factorial(n - 1);
}

long long doublefactorial(int n) {
    if (n < 0)
        return 0;
    if (n < 2)
        return 1;
    return factorial(n) / doublefactorial(n - 1);
}
  • 5!!=1*3*5=15
  • 6!!=2*4*6=48
  • 10!!=2*4*6*8*10=3840
由于整数类型的有限范围和阶乘函数的指数增长,通过计算阶乘并除以前一个数的双阶乘结果来计算双阶乘,对于大于19的数将失败。双阶乘增长也很快,但其对数增长速度是前一个数的一半和阶乘函数一样

下面是一个递归函数:

long factorial(int n, int factor)
{
    if (n == 0)
        return factor;

    return factorial(n-1, factor * n);
}

factorial(5, 1); // 120
unsigned long long doublefactorial(int n) {
    if (n < 0)
        return 0;
    if (n < 2)
        return 1;
    return n * doublefactorial(n - 2);
}
unsigned long long doublefactorial_helper(int n, unsigned long long res) {
    if (n < 2)
        return res;
    return doublefactorial(n - 2, res * n);
}

unsigned long long doublefactorial(int n) {
    return doublefactorial_helper(n, n >= 0);
}
无符号长双阶乘(int n){
if(n<0)
返回0;
if(n<2)
返回1;
返回n*双阶乘(n-2);
}
下面是一个带有辅助函数的尾部递归实现:

long factorial(int n, int factor)
{
    if (n == 0)
        return factor;

    return factorial(n-1, factor * n);
}

factorial(5, 1); // 120
unsigned long long doublefactorial(int n) {
    if (n < 0)
        return 0;
    if (n < 2)
        return 1;
    return n * doublefactorial(n - 2);
}
unsigned long long doublefactorial_helper(int n, unsigned long long res) {
    if (n < 2)
        return res;
    return doublefactorial(n - 2, res * n);
}

unsigned long long doublefactorial(int n) {
    return doublefactorial_helper(n, n >= 0);
}
unsigned long long doublefactorial\u helper(int n,unsigned long-long res){
if(n<2)
返回res;
返回双阶乘(n-2,res*n);
}
无符号长双阶乘(int n){
返回doublefactorial_helper(n,n>=0);
}

将第一个函数转换为尾部递归函数的技巧是,不要等待结果,然后乘以
n
,将更新的中间结果传递给递归函数。乘法的执行顺序相反,但会产生相同的结果(甚至模
ULLONG_MAX+1
).

如果你稍微扩展一下你的数学,你会得到阶乘函数结果在最终结果的分子和分母之间迭代

这段代码将在Python中实现这一点

def _factorial(n, m):
    if n < 0:
        return 0
    elif n == 0:
        return 1.0 * m
    return _factorial(n - 1, n * m)

def factorial(n):
    return _factorial(n, 1)

def _doublefactorial(n, m, is_even):
    if n < 0:
        return 0
    elif n < 2:
        return 1.0 * m

    if is_even:
        m *= factorial(n)
    else:
        m /= factorial(n)

    return _doublefactorial(n - 1, m, (not is_even))

def doublefactorial(n):
    return _doublefactorial(n, 1, True)
def_阶乘(n,m):
如果n<0:
返回0
elif n==0:
返回1.0*m
返回因子(n-1,n*m)
def阶乘(n):
返回因子(n,1)
def_双阶乘(n,m,is_偶数):
如果n<0:
返回0
elif n<2:
返回1.0*m
如果是偶数:
m*=阶乘(n)
其他:
m/=阶乘(n)
返回_双阶乘(n-1,m,(非偶数))
def双阶乘(n):
返回双阶乘(n,1,真)
在C中:

unsigned int _factorial(const unsigned int n, const unsigned int m) {
    if (n < 0) {
        return 0;
    } else if (n == 0) {
        return m;
    }
    return _factorial(n - 1, n * m);
}

unsigned int factorial(const unsigned int n) {
    return _factorial(n, 1);
}

double _doublefactorial(const unsigned int n, const double m, const char is_even) {
    double value = m;

    if (n < 0) {
        return 0;
    } else if (n < 2) {
        return m;
    }

    if (is_even) {
        value *= factorial(n);
    } else {
        value /= factorial(n);
    }

    return _doublefactorial(n - 1, value, !is_even);
}

double doublefactorial(const unsigned int n) {
    return _doublefactorial(n, 1, 1);
}
unsigned int\u阶乘(常数unsigned int n,常数unsigned int m){
if(n<0){
返回0;
}else如果(n==0){
返回m;
}
返回因子(n-1,n*m);
}
无符号整数阶乘(常数无符号整数n){
返回因子(n,1);
}
double _doublefactorial(常数无符号整数n,常数double m,常数char为偶数){
双值=m;
if(n<0){
返回0;
}else if(n<2){
返回m;
}
如果(是偶数){
值*=阶乘(n);
}否则{
值/=阶乘(n);
}
返回双阶乘(n-1,值,!为偶数);
}
双双阶乘(常数无符号整数n){
返回双阶乘(n,1,1);
}

向我们展示您对尾部递归的尝试我建议您首先尝试阶乘函数的尾部递归版本(这在互联网上更容易找到)@muyustan他们要求我们只从n=0到n执行=20@nicomp我没有尝试,因为我不知道怎么做,我知道我需要向函数中添加更多的变量,但不知道如何将其转换为尾部递归。n!!=n(n-2)(n-4)…(1或2取决于n是奇数还是偶数).所以一个计算n的尾部递归函数!!看起来几乎和n的一样!我知道如何在正则阶乘上进行尾部递归,我不知道如何在我问的问题上进行尾部递归,所以如果你知道的话,这会很有帮助。在我看来,这个问题的任何有用答案都将解释为什么提供的版本是尾部-递归。尾部递归函数只是一个递归函数,它返回递归调用而不执行任何其他操作(不乘/加/除任何值)。盖伊,看看我发布的等式,我还知道如何将尾部阶乘和尾部双阶乘分开。莱特利,我如何对等式进行尾部递归