Я пытаюсь реализовать модульную экспансионизацию, но я не могу получить правильный ответ:
public static BigInteger modPow (BigInteger b, BigInteger e, BigInteger m)
{//Вычисление модульной экспоненциальности и возврат объекта класса BigInteger
BigInteger x= new BigInteger("1"); //The default value of x
BigInteger power ;
power=b.mod(m);
String t =e.toString(2); //convert the power to string of binary
String reverse = new StringBuffer(t).reverse().toString();
for (int i=0;i<reverse.length();i++ ) { //this loop to go over the string char by char by reverse
if(reverse.charAt(i)=='1') { //the start of if statement when the char is 1
x=x.multiply(power);
x=x.mod(m);
power=power.multiply(power);
power=power.mod(m);
} //the end of if statement
}//the end of for loop
return x;
} //the end of the method modPow
Вы ничего не делаете для экспоненциальных бит нуля. Вы не получите одинаковые результаты для показателя степени 2 0 и показателя 2 2048?
Эти утверждения должны выходить из предложения if
и выполняться на каждой итерации цикла, независимо от того, равен ли бит нулю или одному:
power=power.multiply(power);
power=power.mod(m);
Кроме того, итерация над битами экспоненты с использованием e.testBit(i)
была бы более эффективной и понятной. Даже если использование modPow()
не разрешено, testBit()
должно быть в порядке.
Здесь моя версия, включая исправление для ошибки и мое предложение, чтобы избавиться от преобразования строк. Он также надежно работает для общих чисел. Он не обрабатывает отрицательные показатели и некоторые другие особые случаи.
public class CrazyModPow
{
public static void main(String[] argv)
{
for (int count = 1; true; ++count) {
Random rnd = new Random();
BigInteger base = BigInteger.probablePrime(512, rnd);
BigInteger exp = BigInteger.probablePrime(512, rnd);
BigInteger mod = BigInteger.probablePrime(1024, rnd);
if (!base.modPow(exp, mod).equals(modPow(base, exp, mod))) {
System.out.println("base: " + base);
System.out.println("exp: " + exp);
System.out.println("mod: " + mod);
}
else if ((count % 10) == 0) {
System.out.printf("Tested %d times.%n", count);
}
}
}
public static BigInteger modPow(BigInteger base, BigInteger e, BigInteger m)
{
BigInteger result = BigInteger.ONE;
base = base.mod(m);
for (int idx = 0; idx < e.bitLength(); ++idx) {
if (e.testBit(idx)) {
result = result.multiply(base).mod(m);
}
base = base.multiply(base).mod(m);
}
return result;
}
}