计算非常大数JAVA的Euler's函数

时间:2012-11-04 07:22:10

标签: java optimization cryptography public-key-encryption factorization

我设法得到了Eulers Totient Function的一个版本,虽然它适用于较小的数字(与我需要计算的1024位数相比,这里更小)

我的版本在这里 -

public static BigInteger eulerTotientBigInt(BigInteger calculate) { 

    BigInteger count = new BigInteger("0");
    for(BigInteger i = new BigInteger("1"); i.compareTo(calculate) < 0; i = i.add(BigInteger.ONE)) { 
        BigInteger check = GCD(calculate,i);

        if(check.compareTo(BigInteger.ONE)==0)  {//coprime
            count = count.add(BigInteger.ONE);          
        }
    }
    return count;
}

虽然这适用于较小的数字,但它的工作原理是迭代从1到计算的数字。对于大型BigIntegers,这是完全不可行的。

我已经读过,每次迭代都可以划分数字,无需逐个查看。我只是不确定我应该用什么来划分(我在C中看到的一些例子是使用long和一个平方根 - 据我所知我无法准确准确地准确BigInteger的平方根。我也想知道如果对于像这样的模运算,函数是否需要包含一个说明mod是什么的参数。我完全不确定这个,所以任何建议都非常赞赏。

有人能指出我在正确的方向吗?

PS我在找到modifying Euler Totient Function时删除了这个问题。我改编它与BigIntegers合作 -

public static BigInteger etfBig(BigInteger n) {

    BigInteger result = n;
    BigInteger i;

    for(i = new BigInteger("2"); (i.multiply(i)).compareTo(n) <= 0; i = i.add(BigInteger.ONE)) {
         if((n.mod(i)).compareTo(BigInteger.ZERO) == 0) 
         result = result.divide(i);
         while(n.mod(i).compareTo(BigInteger.ZERO)== 0 ) 
             n = n.divide(i);
     }      
 if(n.compareTo(BigInteger.ONE) > 0)
 result = result.subtract((result.divide(n)));
 return result;
}

它确实给出了一个准确的结果,当传递一个1024位的数字时,它会永远运行(我仍然不确定它是否已经完成,它已经运行了20分钟)。

3 个答案:

答案 0 :(得分:10)

有一个totient函数的公式,它需要n的素数因子分解。 看here

公式为:

phi(n) = n * (p1 - 1) / p1 * (p2 - 1) / p2 ....
were p1, p2, etc. are all the prime divisors of n.

请注意,您只需要BigInteger,而不是浮点数,因为除法总是精确的。

所以现在问题被简化为找到所有素因子,这比迭代更好。

以下是整个解决方案:

int n;  //this is the number you want to find the totient of
int tot = n; //this will be the totient at the end of the sample
for (int p = 2; p*p <= n; p++)
{
    if (n%p==0)
    {
        tot /= p;
        tot *= (p-1);
        while ( n % p == 0 ) 
            n /= p;
    }
}
if ( n > 1 ) { // now n is the largest prime divisor
    tot /= n;
    tot *= (n-1);
}

答案 1 :(得分:1)

您尝试编写的算法等同于对参数n进行分解,这意味着您应该期望它永远运行,实际上直到您的计算机死亡或者您死亡为止。有关详细信息,请参阅mathoverflow中的这篇文章:How hard is it to compute the Euler totient function?

另一方面,如果你想要一个具有因子分解的大数的totient的值,则将参数作为(prime,exponent)对的序列传递。

答案 2 :(得分:0)

etfBig方法存在问题 对于所有因子,欧拉的乘积公式为n *((因子-1) /因子)。 注意:Petar的代码为:

openssl x509 -in cert.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

在etfBig方法中,替换-inform der

tot /= p; tot *= (p-1);

从2到200的测试然后产生与常规算法相同的结果。