функция модульного возведения в степень дает неверный результат для большого ввода в c

Я пробую две функции для модульного возведения в степень для большой базы, возвращающей неверные результаты. Одна из функций:

uint64_t modular_exponentiation(uint64_t x, uint64_t y, uint64_t p) 
{ 
    uint64_t res = 1;      // Initialize result 
    x = x % p;  // Update x if it is more than or  
                // equal to p 
    while (y > 0) 
    { 
        // If y is odd, multiply x with result 
        if (y & 1) 
            res = (res*x) % p;   
        // y must be even now 
        y = y>>1; // y = y/2 
        x = (x*x) % p;   
    } 
    return res; 
}

Для ввода x = 1103362698 ,y = 137911680 , p=1217409241131113809; возвращается значение (x^y mod p):749298230523009574 (неверно).

Правильное значение: 152166603192600961

Другая функция, которую я пробовал, дала тот же результат. Что не так с этими функциями? Другой:

long int exponentMod(long int A, long int B, long int C) 
{ 
    // Base cases 
    if (A == 0) 
        return 0; 
    if (B == 0) 
        return 1; 
    // If B is even 
    long int y; 
    if (B % 2 == 0) { 
        y = exponentMod(A, B / 2, C); 
        y = (y * y) % C; 
    } 
    // If B is odd 
    else { 
        y = A % C; 
        y = (y * exponentMod(A, B - 1, C) % C) % C; 
    }   
    return (long int)((y + C) % C); 
} 

person superstack    schedule 06.09.2019    source источник
comment
Если x = 1103362698, y = 137911680 и p=137911680, то 152166603192600961 не может быть правильным значением, поскольку оно больше, чем p. Я получил 136204416, когда запустил эту функцию с этими параметрами.   -  person dbush    schedule 06.09.2019
comment
И согласно dcode.fr/modular-exponentiation, это правильный ответ.   -  person dbush    schedule 06.09.2019
comment
извините p=152166603192600961, я уже редактирую свой вопрос   -  person superstack    schedule 06.09.2019


Ответы (1)


При p = 1217409241131113809 это значение, а также любые промежуточные значения для res и x будут больше 32 бит. Это означает, что умножение двух из этих чисел может привести к значению, превышающему 64 бита, что приводит к переполнению используемого вами типа данных.

Если вы ограничите параметры 32-битными типами данных и используете 64-битные типы данных для промежуточных значений, тогда функция будет работать. В противном случае вам нужно будет использовать библиотеку больших чисел, чтобы получить правильный вывод.

person dbush    schedule 06.09.2019
comment
есть какой-то простой способ (чтобы сделать это)? - person superstack; 06.09.2019