【问题标题】:How to compute a modular exponentiation in Crystal?如何在 Crystal 中计算模幂?
【发布时间】:2020-04-14 16:58:46
【问题描述】:

我想在 Crystal 中计算 1_299_709 ** 1_300_751 % 104_729

在 Python 中,pow 函数允许将模数作为第三个参数传递:

❯ python
>>> pow(1_299_709, 1_300_751, 104_729)
90827

在 Ruby 中也是如此:

❯ irb
irb(main):001:0> 1_299_709.pow(1_300_751, 104_729)
=> 90827

但是在Crystal中,好像没有这样的功能,自然,使用**操作符很快就会溢出:

❯ crystal eval "1_299_709 ** 1_300_751 % 104_729"
Unhandled exception: Arithmetic overflow (OverflowError)
  from /usr/lib/crystal/int.cr:0:9 in '**'
  from /eval:1:1 in '__crystal_main'
  from /usr/lib/crystal/crystal/main.cr:97:5 in 'main_user_code'
  from /usr/lib/crystal/crystal/main.cr:86:7 in 'main'
  from /usr/lib/crystal/crystal/main.cr:106:3 in 'main'
  from __libc_start_main
  from _start
  from ???

如何在 Crystal 中计算模幂?


编辑:为了澄清,我已经在使用BigInt,但这不起作用。为了简单起见,我从最小的工作示例中删除了 BigInt。

以下 Python 代码包含我的程序中的实际数字:

>>> pow(53583115773616729421957814870755484980404298242901134400501331255090818409243, 28948022309329048855892746252171976963317496166410141009864396001977208667916, 115792089237316195423570985008687907853269984665640564039457584007908834671663)
75711134420273723792089656449854389054866833762486990555172221523628676983696

它很容易执行并返回正确的结果。 Ruby 也一样:

irb(main):001:0> 53583115773616729421957814870755484980404298242901134400501331255090818409243.pow(2894802230932904885589274625217197696331749616641014100986
4396001977208667916, 115792089237316195423570985008687907853269984665640564039457584007908834671663)
=> 75711134420273723792089656449854389054866833762486990555172221523628676983696

然而,水晶:

a = BigInt.new 53583115773616729421957814870755484980404298242901134400501331255090818409243
e = BigInt.new 28948022309329048855892746252171976963317496166410141009864396001977208667916
p = BigInt.new 115792089237316195423570985008687907853269984665640564039457584007908834671663
y = a ** e % p # overflows with and without BigInt

导致:

gmp: overflow in mpz type
Program received and didn't handle signal IOT (6)

如何在 Crystal 中计算如此庞大的模幂?


编辑: 提交问题以确保它不是错误:crystal-lang/crystal#8612

【问题讨论】:

    标签: math modulo crystal-lang exponentiation


    【解决方案1】:

    正如 Github 问题中所述,这可以通过从 gmp 绑定 mpz_powm_sec 轻松规避:

    这很简单: https://carc.in/#/r/89qh

    require "big/big_int"
    
    a = BigInt.new "53583115773616729421957814870755484980404298242901134400501331255090818409243"
    e = BigInt.new "28948022309329048855892746252171976963317496166410141009864396001977208667916"
    p = BigInt.new "115792089237316195423570985008687907853269984665640564039457584007908834671663"
    
    @[Link("gmp")]
    lib LibGMP
      fun mpz_powm_sec = __gmpz_powm_sec(rop : MPZ*, base : MPZ*, exp : MPZ*, mod : MPZ*)
    end 
    
    #y = a ** e % p
    y = BigInt.new
    LibGMP.mpz_powm_sec(y, a, e, p)
    puts y
    
    # > 75711134420273723792089656449854389054866833762486990555172221523628676983696
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-24
      • 2015-07-22
      • 1970-01-01
      • 2018-01-15
      • 1970-01-01
      相关资源
      最近更新 更多