( a ^ b ) mod c

Тема в разделе "WASM.A&O", создана пользователем _DEN_, 11 апр 2005.

  1. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Блин, все никак не могу домучить универское задание по RSA :dntknw:



    a, b, c - натуральные, порядка нескольких сотен. Как по-человечески посчитать выражение ( a ^ b ) mod c ? ОЧЕНЬ не хочется писать класс для работы с большими числами. Как в данном случае обойтись старым советским DWORD-ом ?
     
  2. yureckor

    yureckor New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2004
    Сообщения:
    494
    Адрес:
    Russia
  3. Sergey_R

    Sergey_R Member

    Публикаций:
    0
    Регистрация:
    9 янв 2005
    Сообщения:
    138
    _DEN_

    А в чем проблема? У тебя числа
    , т.е. в двойное слово ты влезаешь без проблем. Или ты сначала собираешься вычислить ВСЕ значение степени, а ПОТОМ вычислять модуль? Так это НЕ ОБЯЗАТЕЛЬНО! Ты можешь ПОСЛЕ КАЖДОГО умножения брать значение по модулю и дальше продолжать работать только с ним. В результате у тебя промежуточные значения всегда будут умещаться в двойном слове.

    И посмотри приведенный yureckor архив. Там есть краткое описание, где сказано, как значительно ускорить вычисление степени.

    (Ну а если же я тебя неверно понял, и проблема в другом, то извини...)
     
  4. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Sergey_R

    Понял нормально ;)



    Тоесть... Блин, что-то я не понял :)



    Давай на примере:



    (117 ^ 341) mod 514.



    Ты хочешь сказать что



    (117 ^ 341) mod 514 = ((((117 mod 514) * 117) mod 514) * 117) mod 514) ... итд 341 раз ...)



    Так чтоли?
     
  5. OLS

    OLS New Member

    Публикаций:
    0
    Регистрация:
    8 янв 2005
    Сообщения:
    322
    Адрес:
    Russia
    Так, только еще более эффективно - возводи некую переменную с начальным значением 117 в квадрат по модулю 514 и домножай на нее тоже по модулю там где нужно.



    Только вот вопрос есть в ограничениях на взаимную простоту a и с.
     
  6. Sergey_R

    Sergey_R Member

    Публикаций:
    0
    Регистрация:
    9 янв 2005
    Сообщения:
    138
    _DEN_



    Да, именно! Арифметика по модулю это позволяет.

    НО!
    только, если делать "в лоб" ;о)



    Смотри. Допустим, Тебе нужно возвести в степень 8: a^8. Ты можешь 8 раз a*a*a*a*a*a*a*a, а можешь - ((a^2)^2)^2). Не 8 умножений (и взятий по модулю. а всего 3!

    Или b=18=16+2 -> a^b ->

    a^18 = (a^(16+2)) = (a^16)*(a^2) = ((((a^2)^2)^2)^2)*(a^2) или

    a^18 = (a^((8+1)*2)) = ((a^(8+1))^2) = ((((a^2)^2)^2)*a)^2



    То есть, начиная со старшего бита проверяешь, если очередной бит равен "1", то умножаешь промежуточный результат на "a". Если биты еще не кончились, умножаешь промежуточный результат сам на себя (возможишь в квадрат), и переходишь к следующему биту.



    Что-то вроде:
    Код (Text):
    1. temp = a; // в любом случае, кроме b=0, тогда temp = 1.
    2. while ("просмотр битов от старшего к младшему")
    3. {
    4.   temp = temp * temp;
    5.   if ("очередной бит" == 1)  temp = temp * a;
    6. }


    Ну и, естественно, взятие каждого промежуточного результата по модулю... ;о)
     
  7. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Sergey_R

    Так... Спасибо, тут надо помедитировать ;)