Возведение большого числа в большую степень и модификация на большое число?

Я застрял с, вероятно, простым вопросом. У меня есть 3 больших числа (A, B, C), все целые числа, и мне нужно сделать следующее: привести A к B и по модулю результата на C, а затем проверить, равен ли результат 1. Вот мой код:

double power = fmod((pow((double)A,(double)B)),(double)C);
    if (power != 1){
        printf("Something!\n");
    }

И это не работает (я пробовал небольшие числа, например, 17 с питанием от 28 и модулем с 29). Любые предложения по этому поводу?


person Z1kkurat    schedule 26.11.2014    source источник
comment
насколько большими они могут быть?   -  person UmNyobe    schedule 26.11.2014
comment
stackoverflow.com/a/16665530/971127   -  person BLUEPIXY    schedule 26.11.2014
comment
возможный дубликат поиск a^b^c^... mod m   -  person phuclv    schedule 26.11.2014
comment
@LưuVĩnhPhúc Я ничего не говорю о bigint.   -  person BLUEPIXY    schedule 26.11.2014
comment
@BLUEPIXY извините, я открыл не ту страницу   -  person phuclv    schedule 26.11.2014
comment
@UmNyobe Потенциально их может быть до миллионов, я пытаюсь построить свою реализацию теста на простоту Лукаса (не Лукаса-Лемера), и одна из операций - это число от 0 до N с помощью N-1 и модулирование результата.   -  person Z1kkurat    schedule 26.11.2014


Ответы (3)


Попробуйте это (во избежание арифметического переполнения):

unsigned long long power = 1;
A %= C;
while (B > 0)
{
    power = (power * A) % C;
    B--;
}

Вы можете дополнительно улучшить производительность во время выполнения следующим образом:

unsigned long long power = 1;
A %= C;
while (B > 0)
{
    if (B & 1)
        power = (power * A) % C;
    B >>= 1;
    A = (A * A) % C;
}
person barak manos    schedule 26.11.2014
comment
Это работает, если A, B и C имеют тип int, а unsigned long long в два раза больше, чем int. Но мы не знаем, насколько велики эти числа и какого они типа. - person phuclv; 26.11.2014
comment
@LưuVĩnhPhúc: Правильно, но вопрос ничего не говорит о максимальных значениях входных аргументов (A, B и C), поэтому я сделал все возможное с данной информацией... - person barak manos; 26.11.2014
comment
да, но на самом деле это был ответ на многие другие вопросы раньше, и это просто дубликат - person phuclv; 26.11.2014
comment
@LưuVĩnhPhúc на самом деле их может быть до миллионов или даже миллиардов, поскольку я пытаюсь построить свою реализацию теста простоты Лукаса (не Лукаса-Лемера), и одна из операций - это число от 0 до N с помощью N-1 и модулирование результат. - person Z1kkurat; 26.11.2014

Минимальный и максимальный размеры для Double равны -1,7*10^308 и 1,7*10^308 соответственно. Если вам нужно больше, вы можете попробовать долго.

Не уверен, почему вы используете fmod. Но это должно делать то, что вы хотите.

double power = ( pow(A, B) ) % C;
if (power != 1){
        printf("Something!\n");
    }
person Jacobr365    schedule 26.11.2014
comment
% не работает с целочисленными типами. Кроме того, это неверно, потому что double точен только до первых нескольких цифр. - person phuclv; 26.11.2014
comment
Работает на моем компьютере просто отлично, используя его пример 17, 28, 29. Я получаю 1 для этого примера, который соответствует WolfRamAlpha. - person Jacobr365; 26.11.2014
comment
Это работает по чистой случайности. Кроме того, на моем компьютере он возвращает 12, если я привожу результат pow к unsigned long long, и 0, если я привожу к unsigned int. 17 ^ 28 требует примерно 114,449 бит, и определенно double не может иметь такой большой точности на современных машинах. - person phuclv; 26.11.2014

попробуйте этот подход

double a,b,c;

a = 1124124124254234;
b = 1124124124254234 * 5;
c = 1124124124254234 * 2;

double power = pow(a,b); 

double mod = fmod(power, c);

if (mod != 1){
    printf("Something!\n");
}
person Rafael    schedule 26.11.2014
comment
как и выше, % не работает с целочисленными типами, и результат неверен из-за ограниченной точности double - person phuclv; 26.11.2014
comment
@LưuVĩnhPhúc % работает только с целым числом, с двойным не работает. - person mch; 26.11.2014