当前位置: 首页 > 面试题库 >

为什么pow(a,d,n)比a ** d%n快得多?

宗政元青
2023-03-14
问题内容

我试图实施Miller-
Rabin素数测试
,并且对为什么中型数字(〜7位数字)花费如此长时间(>
20秒)感到困惑。我最终发现以下代码行是问题的根源:

x = a**d % n

(其中adn都是相似的,但不相等的中号,**是幂运算符,并且%是模运算符)

然后,我尝试将其替换为以下内容:

x = pow(a, d, n)

相比之下,它几乎是瞬时的。

对于上下文,这是原始功能:

from random import randint

def primalityTest(n, k):
    if n < 2:
        return False
    if n % 2 == 0:
        return False
    s = 0
    d = n - 1
    while d % 2 == 0:
        s += 1
        d >>= 1
    for i in range(k):
        rand = randint(2, n - 2)
        x = rand**d % n         # offending line
        if x == 1 or x == n - 1:
            continue
        for r in range(s):
            toReturn = True
            x = pow(x, 2, n)
            if x == 1:
                return False
            if x == n - 1:
                toReturn = False
                break
        if toReturn:
            return False
    return True

print(primalityTest(2700643,1))

定时计算示例:

from timeit import timeit

a = 2505626
d = 1520321
n = 2700643

def testA():
    print(a**d % n)

def testB():
    print(pow(a, d, n))

print("time: %(time)fs" % {"time":timeit("testA()", setup="from __main__ import testA", number=1)})
print("time: %(time)fs" % {"time":timeit("testB()", setup="from __main__ import testB", number=1)})

输出(与PyPy 1.9.0一起运行):

2642565
time: 23.785543s
2642565
time: 0.000030s

输出(在Python 3.3.0中运行,2.7.2返回的时间非常相似):

2642565
time: 14.426975s
2642565
time: 0.000021s

还有一个相关的问题,为什么使用Python
2或3运行时,这种计算几乎比使用PyPy时快一倍,而通常PyPy要快得多?


问题答案:

请参阅Wikipedia上有关模幂的文章。基本上,当您这样做时a**d % n,实际上必须计算a**d,这可能会很大。但是有很多计算方法,a**d % n而不必自己计算a**d,这就是pow它的作用。该**运营商不能做到这一点,因为它不能“预见未来”知道你要立即采取模数。



 类似资料:
  • 问题内容: 我正在学习Go,并且一直沉迷于Go旅游(exercise- stringer.go:https : //tour.golang.org/methods/7)。 这是一些代码: 所以我想出了is 的内部表示,所以散布算子起作用了。但我得到: 有没有搞错?字符串切片也不起作用,这是怎么回事? 编辑 :对不起,我的问题中有一个错误- 错误是关于type的,不是。我在玩代码,并且粘贴了错误的输

  • 描述 (Description) 字符类[ad[mp]]匹配从a到d或m到p的任何字符。 例子 (Example) 以下示例显示了字符类匹配的用法。 package com.wenjiangs; import java.util.regex.Matcher; import java.util.regex.Pattern; public class CharacterClassDemo { p

  • 我有一个数组。我想对它们进行排序并删除重复项。这个答案建议使用和进行这种操作。运算的顺序不应该改变结果,所以我测量了计算的时间。 是什么使一个比另一个快?还有,有没有更快的办法呢?

  • 问题内容: 我编写了两种方法的代码,以找出LeetCode字符串中的第一个唯一字符。 问题陈述: 给定一个字符串,找到其中的第一个非重复字符并返回其索引。如果不存在,则返回-1。 示例测试用例: s =“ leetcode”返回0。 s =“ loveleetcode”,返回2。 方法1(O(n))(如果我错了,请纠正我): 方法2(O(n ^ 2)): 在方法2中,我认为复杂度应为O(n ^ 2

  • 维基百科说A*在O(E)中运行,其中E是图中的边数。但我的朋友说a*只是Dijkstra算法的一般情况,而Dijkstra算法运行在O(E+V log V)中。所以我很困惑为什么A*比Dijkstra的算法跑得更快。

  • 任务给你一个排序的整数数组arr。它包含几个唯一的整数(负、正或零)。 您的任务是找到最大的d,使得a b c=d,其中a、b、c和d是arr的不同元素。如果没有找到这样的元素d,则返回null。 例子: 对于arr=[2,3,5,7,12],输出应该是12(这个数组正确传递了我的函数) 对于arr=[-100,-1,0,7,101],输出应该是0(这个不通过) 我可以进行正数检查,但我的函数因负