Быстрые вычисления по модулю в Python и Ruby - PullRequest
6 голосов
/ 30 марта 2011

Мне дали следующий алгоритм, который вычисляет s, где s = g ^ u mod p в Python:

def modexp ( g, u, p ):
   """computes s = (g ^ u) mod p
      args are base, exponent, modulus
      (see Bruce Schneier's book, _Applied Cryptography_ p. 244)"""
   s = 1
   while u != 0:
      if u & 1:
         s = (s * g)%p
      u >>= 1
      g = (g * g)%p;
   return s

Однако, когда я конвертирую код в Ruby примерно так:

def modexp ( g, u, p )
    s = 1
    while u != 0
        if u & 1
            s = (s * g)%p
        end
        u >>= 1
        g = (g * g)%p
    end
    return s
end

Я получаю другой вывод.Например:

Python 2.7 (r27:82500, Oct  6 2010, 12:29:13) 
[GCC 4.5.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import modexp
>>> modexp.modexp(96,25,17)
6

Какой правильный ответ из кода Python по сравнению с

>> require './modexp.rb'
=> true
>> modexp(96,25,17)
=> 14

Может кто-нибудь объяснить это?Из того, что я прочитал, Python и Ruby имеют одинаковый синтаксис для битового сдвига и побитового кодирования и используются в коде, поэтому я не думаю, что это так.У кого-нибудь есть другие идеи?

Ответы [ 2 ]

6 голосов
/ 30 марта 2011

Это потому, что поразрядно - & возвращает число , а 0 в Python "falsey", но в Ruby "truey".

def modexp ( g, u, p )
    s = 1
    while u != 0
        puts "g: #{g}, s: #{s}, u: #{u.to_s(2)}"
        if u & 1
            s = (s * g)%p
        end
        u >>= 1
        g = (g * g)%p
    end
    return s
end

irb(main):032:0> modexp(96,25,17)
g: 96, s: 1, u: 11001
g: 2, s: 11, u: 1100
g: 4, s: 5, u: 110
g: 16, s: 3, u: 11
g: 1, s: 14, u: 1
=> 14

Обратите внимание, что s изменяется междувторая строка и третья, хотя u даже в этой точке.Помня, что 1100 = 12, мы видим, что 12 & 1 == 0.Итак, в Python тест if u & 1: не пройден;но в Ruby, где 0 считается значением true , if u & 1 успешно .

Попробуйте заменить эту строку на if u & 1 != 0.

3 голосов
/ 30 марта 2011

0 не является ложным значением в Ruby. Вам нужно изменить if u&1 на if (u&1) != 0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...