二元权力给我一个错误的结果

时间:2016-05-31 22:12:30

标签: c binary overflow largenumber

我的二进制供电功能有问题。包含结果的变量在执行乘法时溢出并给出错误的结果。当源值大于4,312,952,827时会发生这种情况。那么我该如何解决这个问题呢?这是我的功能代码。

unsigned long long binpow(unsigned long long a, unsigned long long n, unsigned long long m)
{
    unsigned long long res;
    res=1;
    while (n)
    {
        if (n & 1)
        {
            res=(res*a)%m;
            n--;
        }
        a=(a*a)%m;
        n >>= 1;
    }
    return res;
}

2 个答案:

答案 0 :(得分:1)

表达式a*a需要的空间是源的大小的两倍。在您的方案4,312,952,827 > 2^32-1中,您已超出unsigned long long的范围。

实现模块化指数二进制梯形图的经验法则是能够对参数数据类型的至少两倍的范围执行算术运算,因此在您的情况下它是128位。

答案 1 :(得分:0)

你的残差和模数都超过unsigned long long的宽度(偏移m)。

您可以使用类似unsigned __int128的编译器扩展类型来解决问题,这会产生4,312,952,827的正确结果。

unsigned __int128 binpow(unsigned __int128 a, unsigned __int128 n, unsigned __int128 m)
{
    unsigned __int128 res;
    res = 1;
    while (n)
        {
            if (n & 1)
                {
                    res = (res*a)%m;
                    n--;
                }
            a = (a*a) % m;
            n >>= 1;
        }
    return res;
}

或者,如果您想以安全的方式处理大量数字,可以使用通用的bignum库,例如gmplib