C函数返回错误的int值

时间:2014-11-18 13:29:29

标签: c return return-value exponentiation

所以我在C中得到了一个模幂运算函数,看起来像这样。

int modexp(int m, int e, int n)
{
    printf("%i\n", m);
    printf("%i\n", e);
    printf("%i\n", n);
    printf("\n");

    if(e == 0)
    {
        return 1;
    }
    if(e%2 == 1)
    {
        return modexp(m, e-1, n) * m%n;
    }
    else
    {
        int modTemp = modexp(m, (int)(e/2), n);
        modTemp = modTemp * modTemp;
        return modTemp % n;
    }
}

我在main()函数中调用这个

int p = 3511;
printf("%i\n", modexp(2, p-1, p*p));

当打印m,e和n的值时,我得到正确的递归值,最后到e = 0。这是函数应该返回1.它肯定会返回代码中的那个位置,但是不是预期的整数1,我得到-6593454而且我不知道为什么。

完整的代码可以在这里找到: https://gist.github.com/anonymous/7024ac77b2432a381968

任何输入都受到高度赞赏......

4 个答案:

答案 0 :(得分:1)

将n位值与m位值相乘会产生(n + m)位结果。这就是modexp(m, e-1, n) * mmodTemp * modTemp溢出的原因。您需要加宽乘法才能从32位值获得完整的64位结果

return ((int64_t)modexp(m, e-1, n) * m) % n;
...
int64_t modTemp = modexp(m, (int)(e/2), n);
modTemp = modTemp * modTemp;
return modTemp % n;

答案 1 :(得分:0)

您的号码正在溢出,您的号码很可能是32位或64位有符号整数。这意味着最大尺寸可以是2^31=21474836482^63= 9223372036854775807。只需查看modexp(...)乘以m%n的大小即可。那是一个非常大的数字:)

modTemp * modTemp

也是如此

答案 2 :(得分:0)

确实在e == 0时返回了

1,但是这个返回值是在先前递归级别上进行的计算中的一个术语。如果您修改代码如下:

#include <stdio.h>
int modexp(int m, int e, int n)
{
    printf("%i\n", m);
    printf("%i\n", e);
    printf("%i\n", n);
    printf("\n");

    if(e == 0)
    {
        printf("returning 1\n");
        return 1;
    }
    if(e%2 == 1)
    {
        int tmp=modexp(m, e-1, n) * m%n;
        printf("returning %d\n",tmp);
        return tmp; 
    }
    else
    {
        int modTemp = modexp(m, (int)(e/2), n);
        modTemp = modTemp * modTemp;
        modTemp= modTemp % n;
        printf("returning %d\n",modTemp);
        return modTemp;;
    }
}


int main(){
    int p = 3511;
    printf("%d\n", modexp(2, p-1, p*p));
    return 0;
}

您将在结尾处获得此输出:

returning 1
returning 2
returning 4
returning 8
returning 64
returning 4096
returning 8192
returning 5473259
returning 10946518
returning 2217782
returning 5855618
returning 11711236
returning 8916378
returning 5505635
returning -1026672
returning 975519
returning 1951038
returning 195330
returning 390660
returning -6593454
-6593454

这表明e == 0返回的1用于进一步计算。

在某些时候,您的代码会溢出int,这就是您最后得到负数的原因。您应该使用更长的类型。

答案 3 :(得分:0)

我同意它是modTemp变量的溢出。但是,为了清楚起见,我建议只将modTemp的类型从Int更改为long,并使用b / e / m更改m / e / n,如下所示:

#include <stdio.h>

int modexp(int b, int e, int m); // b: base; e: exp; m: modulus


int main()
{
    int p = 3511; // given number p
    printf("%i\n", modexp(2, p-1, p*p)); // last line printed is the remainder of mod exp
}


int modexp(int b, int e, int m)
{
    printf("%i\n", b);
    printf("%i\n", e);
    printf("%i\n", m);
    printf("\n");

    if(e == 0)
    {
        return 1;
    }
    if(e%2 == 1)
    {
        return modexp(b, e-1, m) * b%m;
    }
    else
    {
        long modTemp = modexp(b, (int)(e/2), m); // !!here modTemp is declared as long!!
        modTemp = modTemp * modTemp;
        return modTemp % m;
    }
}