Python和Ruby中的快速模数计算

时间:2011-03-30 12:24:50

标签: python ruby

我已经获得了以下算法来计算Python中的s = g ^ u mod p:

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对于bitshift和bitwise具有相同的语法并在代码中使用,所以我认为不是这样。有没有其他想法?

2 个答案:

答案 0 :(得分:6)

这是因为bitwise-&返回,0为" falsey"在Python中但是" truthy"在Ruby中。

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替换该行。

答案 1 :(得分:3)

0在Ruby中不是假值。您需要将if u&1更改为if (u&1) != 0