Ruby中的大型指数?

时间:2009-11-18 20:02:05

标签: ruby math exponent

我正在做一些与大学相关的Diffie Hellmann练习,并尝试使用红宝石。 可悲的是,红宝石似乎无法处理大型指数:

  

警告:在** b中,b可能太大了   NaN的
  [...]

周围有什么办法吗? (例如,一个特殊的数学课或那条线上的东西?)

P.S。这是有问题的代码:

generator = 7789
prime = 1017473
alice_secret = 415492
bob_secret = 725193

puts from_alice_to_bob = (generator**alice_secret) % prime
puts from_bob_to_alice = (generator**bob_secret) % prime

puts bobs_key_calculation = (from_alice_to_bob**bob_secret) % prime
puts alices_key_calculation = (from_bob_to_alice**alice_secret) % prime

8 个答案:

答案 0 :(得分:10)

您需要执行所谓的modular exponentiation

答案 1 :(得分:3)

如果你可以使用OpenSSL绑定,那么你可以在Ruby中进行快速模幂运算

puts some_large_int.to_bn.mod_exp(exp,mod)

答案 2 :(得分:2)

有一种很好的方法来计算^ b mod n而不会获得这些巨大的数字。

你将自己走一条指数,在每个阶段取模数。 有一个技巧,你可以将其分解为一系列的两个权力。

这是一个链接,其中有一个使用它来做RSA的例子,来自我前一段时间的课程: 具体来说,在第二页上,您可以看到一个示例: http://www.math.uwaterloo.ca/~cd2rober/Math135/RSAExample.pdf

使用维基百科的一些示例伪代码进行更多解释:http://en.wikipedia.org/wiki/Modular_exponentiation#Right-to-left_binary_method

答案 3 :(得分:1)

我不知道红宝石,但即使是一个对bignum友好的数学库也很难以天真的方式评估这样的表达方式(7789对权力415492有大约160万位)。

在没有爆炸的情况下解决a^b mod p的方法是在每次取幂时进行mod p ing - 我猜这种语言不能正常运行它本身,因此必须得到帮助。

答案 4 :(得分:1)

我已经做了一些自己的尝试。到目前为止,通过平方的指数运作良好,但与bigNum相同的问题。

这样一个递归的东西
def exponentiation(base, exp, y = 1)
    if(exp == 0)
        return y
    end
    case exp%2
        when 0 then 
            exp = exp/2
            base = (base*base)%@@mod
            exponentiation(base, exp,  y)
        when 1 then
            y = (base*y)%@@mod
            exp = exp - 1
            exponentiation(base, exp, y) 
    end
end
但是,正如我所知道的那样,依靠红宝石的黄金级别来做任何实质性的事情都是一个可怕的想法。 Ruby使用了Eratosthenes的Sieve作为它的主要生成器,但更糟糕的是,它使用了试验分区用于gcd等......

哦,@@ mod是一个类变量,所以如果你打算自己使用它,你可能想把它作为一个参数添加。

我已经很快就能开始工作了

将a.exponentiation(100000000000000,1222555345678)

该范围内的数字。

(使用@@ mod = 80233)

答案 5 :(得分:1)

好的,让平方法适用于

a = Mod.new(80233788)
puts a.exponentiation(298989898980988987789898789098767978698745859720452521, 12225553456987474747474744778)

输出:59357797

我认为这应该足以解决您在加密课程中遇到的任何问题

答案 6 :(得分:0)

如果你真的想要进行BIG模幂运算,这里是wiki页面的一个实现。

#base expantion number to selected base 
def baseExpantion(number, base)
   q = number
   k = ""
   while q > 0 do
     a = q % base
     q = q / base
     k = a.to_s() + k
   end
     return k
end

#iterative for modular exponentiation 
def modular(n, b, m)
   x = 1
   power = baseExpantion(b, 2) #base two
   i = power.size - 1
   if power.split("")[i] == "1"
      x = x * n
      x = x % m
   end
   while i > 0 do
      n *= n
      n = n % m
      if power.split("")[i-1] == "1"
         x *= n
         x = x % m
      end
      i -= 1
   end
   return x
end

使用wolfram alpha进行测试的结果

答案 7 :(得分:0)

这受到维基百科上的example示例的启发:

def powmod(base, exponent, modulus)
  return modulus==1 ? 0 : begin
    result = 1 
    base = base % modulus
    while exponent > 0 
      result = result*base%modulus if exponent%2 == 1
      exponent = exponent >> 1
      base = base*base%modulus
    end 
  result
  end 
end