ModPow计算速度不够快c#

时间:2018-03-21 17:41:32

标签: c# math biginteger

您好我正在尝试尽快进行ModPow计算,计算结果如此 P ^ e%n 。测试数据是888999000 ^ 202404606%237291793913,我知道BigInteger.ModPow(P,e,n)但是我不应该使用这个函数所以我编写了以下函数,这是相对的慢,我真的需要加快这个过程。 (我相信也许如果我将计算数字分成两半并将其转换为两个单独的计算,它将有希望加快这个过程),无论如何,这是我到目前为止所写的内容。

private static BigInteger ModPow(BigInteger baseNum, BigInteger exponent, BigInteger modulus)
{
    BigInteger c;
    if (modulus == 1)
        return 0;
    c = 1;
    for (BigInteger e_prime = 1; e_prime <= exponent; e_prime++)
    {
        c = (c * baseNum) % modulus;
    }
    return c;
}

2 个答案:

答案 0 :(得分:2)

你需要的是Exponentiation by squaring,它也适用于模幂。代码应该是这样的:

private static BigInteger ModPow(BigInteger baseNum, BigInteger exponent, BigInteger modulus)
{
    BigInteger pow = 1;
    if (modulus == 1)
        return 0;
    BigInteger curPow = baseNum % modulus;
    BigInteger res = 1;
    while(exponent > 0){
        if (exponent % 2 == 1)
            res = (res * curPow) % modulus;
        exponent = exponent / 2;
        curPow = (curPow * curPow) % modulus;  // square curPow
    }
    return res;
}

对于代码而言,此方法的效果为O(log(exponent))而不是O(exponent),以乘法和模运算的数量(O(1)可能不是BigInteger但详细信息取决于关于实施)。另请注意,上面的代码不应该用于任何真实世界的加密相关实现,因为它会引入漏洞(性能取决于exponent的实际值,特别是那里有多少1位(请参阅Timing attack了解一些细节。)

答案 1 :(得分:0)

好吧,试试这个

private static BigInteger ModPow(BigInteger baseNum, BigInteger exponent, BigInteger modulus)
{
       BigInteger B, D;
       B = baseNum;

       B %= modulus;
       D = 1;
       if ((exponent & 1) == 1)
       {
           D = B;
       }

        while (exponent > 1)
        {
             exponent >>= 1;
             B = (B * B) % modulus;
             if ((exponent & 1) == 1)
             {
                 D = (D * B) % modulus;
             }
         }
         return (BigInteger)D;
}