素性测试的Miller-Rabin算法完全解析 (C语言实现、Python实现)

因为文中存在公式,只能用图片方式上传了!

 

以下为C语言源代码:

#include <stdio.h>
typedef long long unsigned LLU;
typedef int BOOL;
#define TRUE 1
#define FALSE 0

BOOL isPrime(LLU n) {  //这是传统的方法,用于与Miller-Rabin算法的结果进行对比。
    if( (n&1)==0 || n%5==0)
        return FALSE;

    LLU i,bnd;
    bnd=sqrt(n);
    for(i=2; i<=bnd; i++)
        if(n%i==0)
            return FALSE;

    return TRUE;
}

//实现(a*b)%c,用类似快速幂的方式实现。
//将模运算下的乘法用加法实现的思想是时间换空间。
//这可以作为典型的时间换空间的例子。
LLU quickMult(LLU a,LLU b,LLU c){
    LLU result=0;
    while(b>0) {
        if(b&1)
            result=(result+a)%c;
        a=(a+a)%c;
        b>>=1;
    }
    return result;
}

//请注意,计算快速幂时,因为变量的数据类型为long long,是64bits长度的整数。
//a的值不能大于(2的32次方-1)≈4000000000
//否则,计算a*a时会越界,超过64bits整数的表示范围。
//例如a,b,c分别为:7087881096594 10000000000036 10000000000037时,
//正确结果 (a^b)%c=1,但是,在此计算的结果不为1。
//因此,可以改进为用“快速乘”代替*乘法运算符,能更加充分第利用64的long long unsigned型的存储空间。
//这个例子可以作为算法改进从O(n)到O(lg(n))的进步的例子。
LLU quickPower(LLU a,LLU b,LLU c) {
    LLU result=1;
    while(b>0) {
        if(b&1)
            //result=result*a%c; //此为直接乘法
            result=quickMult(result,a,c);
        //a=a*a%c; //此为直接乘法
        a=quickMult(a,a,c);
        b>>=1;
    }
    return result;
}

//如果返回值为TRUE表示n为素数,返回值为FALSE表示n为合数。
BOOL MillerRabinPrimeTest(LLU n) {
    LLU d,x,newX,a=1;
    int i;
    for (i=0; i<4; i++)
        a*=rand();
    a=a%(n-3)+2;//随机第选取一个a∈[2,n-2]
    //printf("随机选取的a=%lld\n",a);
    int s=0;//s为d中的因子2的幂次数。
    d=n-1;  //d取初值n-1
    while( (d&1)==0) {//将d中因子2全部提取出来。
        s++;
        d>>=1;
    }

    x=quickPower(a,d,n);
    for(i=0; i<s; i++) { //进行s次二次探测
        newX=quickPower(x,2,n);
        if(newX==1 && x!=1 && x!=n-1)
            return FALSE; //用二次定理的逆否命题,此时n确定为合数。
        x=newX;
    }
    if(x!=1)
        return FALSE;   //用费马小定理的逆否命题判断,此时x=a^(n-1) (mod n),那么n确定为合数。

    return TRUE; //用费马小定理的逆命题判断。能经受住考验至此的数,大概率为素数。
}

//经过连续特定次数的Miller-Rabin测试后,
//如果返回值为TRUE表示n为素数,返回值为FALSE表示n为合数。
BOOL isPrimeByMR(LLU n) {
    if((n&1)==0 || n%5==0)
        return FALSE;
    int i;
    for (i=0; i<100; i++)
        if(MillerRabinPrimeTest(n)==FALSE)
            return FALSE;
    return TRUE;
}

//对比传统方法和Miller-Rabin算法的结果
void check(LLU n) {
    char isRight;
    BOOL resultA,resultB;
    resultA=isPrime(n);
    resultB=isPrimeByMR(n);
    if(resultA==resultB) {
        isRight='V';
        printf("%c,%llu %d %d\n",isRight,n,resultA,resultB);
    } else {
        isRight='X';
        printf("%c,%llu %d %d\n",isRight,n,resultA,resultB);
    }
}

//测试任务:在本人笔记本电脑上测试,N=10的18次方至N+10之间的质数为:
//1000000000000000003
//1000000000000000009
//Miller-Rabin算法的速度:0.22秒
//常规算法:22秒
int main() {    
    srand(time(NULL));

    LLU i,n,N;
    N=1000000000000000000;
    BOOL result;
    for(i=N; i<N+10; i++) {
        n=i;
        //check(n);        
        //result=isPrime(n);
        result=isPrimeByMR(n);
        if(result==TRUE)
            printf("%llu\n",n);

    }
    return 0;
}

 

以下为Python语言源代码:

import math
import randomdef isPrime(n): #这是传统的方法,用于与Miller-Rabin算法的结果进行对比。if (n & 1) == 0 or n % 5 == 0:return Falsebnd = int(math.sqrt(n))for i in range(2, bnd + 1):if n % i == 0:return Falsereturn True# 实现(a*b)%c,用类似快速幂的方式实现。
# 将模运算下的乘法用加法实现的思想是时间换空间。
# 这可以作为典型的时间换空间的例子。
def quickMult(a, b, c):result = 0while b > 0:if b & 1:result = (result + a) % ca = (a + a) % cb >>= 1return result#因为Python支持大整数运算,所以在此也可以不用快速乘法,而直接使用乘法*。
def quickPower(a, b, c):result = 1while b > 0:if (b & 1):# result=result*a%c #此为直接乘法result = quickMult(result, a, c)# a=a*a%c #此为直接乘法a = quickMult(a, a, c)b >>= 1return result#如果返回值为TRUE表示n为素数,返回值为FALSE表示n为合数。
def MillerRabinPrimeTest(n):a = random.randint(2,n-2) #随机第选取一个a∈[2,n-2]# print("随机选取的a=%lld\n"%a)s = 0 #s为d中的因子2的幂次数。d = n - 1while (d & 1) == 0: #将d中因子2全部提取出来。s += 1d >>= 1x = quickPower(a, d, n)for i in range(s): #进行s次二次探测newX = quickPower(x, 2, n)if newX == 1 and x != 1 and x != n - 1:return False #用二次定理的逆否命题,此时n确定为合数。x = newXif x != 1:  # 用费马小定理的逆否命题判断,此时x=a^(n-1) (mod n),那么n确定为合数。return Falsereturn True  # 用费马小定理的逆命题判断。能经受住考验至此的数,大概率为素数。# 经过连续特定次数的Miller-Rabin测试后,
# 如果返回值为TRUE表示n为素数,返回值为FALSE表示n为合数。
def isPrimeByMR(n):if ((n & 1) == 0 or n % 5 == 0):return Falsefor i in range(100):if MillerRabinPrimeTest(n) == False:return Falsereturn True#对比传统方法和Miller-Rabin算法的结果
def check(n):resultA = isPrime(n)resultB = isPrimeByMR(n)if resultA == resultB:isRight = 'V'print("%c,%u %d %d" % (isRight, n, resultA, resultB))else:isRight = 'X'print("%c,%u %d %d" % (isRight, n, resultA, resultB))# 测试任务:在本人笔记本电脑上测试,N=10的18次方至N+10之间的质数为:
# 1000000000000000003
# 1000000000000000009
# Miller-Rabin算法的速度:0.22秒
# 常规算法:22秒
# python的常规算法,耗时更长。
def main():# freopen("result.txt","w",stdout)random.seed()# res=quickPower(2,10,7)# print("%u"%res)N = 1000000000000000000for i in range(N, N + 10):n = i#check(n)# n=int(input())#result=isPrime(n)result = isPrimeByMR(n)if result == True :print("%u" % n)return 0# print(isPrime(1000000000000000003))
# a, b, c = [int(e) for e in input().split(" ")]
# print(quickPower(a,b,c))
# # 7087881096594 10000000000036 10000000000037 =1
main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/262370.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MongoDB源码阅读之ReplSet源码分析

1. ReplSet源码结构 rs_config.h replSet间同步设置的工具类 rs_member.h 心跳检测类和replSet成员状态的定义 rs_sync.h 同步数据类 rs.h 定义了几乎所有replSet相关的类&#xff08;Member:replSet中的节点成员&#xff0c; GhostSync&#xff1a;备份同步类&#xff0c;Rep…

C# 字符串性能

Written By Dr Herbie [2] Translated By Allen Lee Introduction 你在代码中处理字符串的方法可能会对性能产生令人吃惊的影响。程序中需要考虑两个由于使用字符串而产生的问题&#xff1a;临时字符串变量的使用和字符串连接。Background1.String是引用类型&#xff0c;在堆上…

手把手教你部署VSAN见证虚拟设备 (Cormac)

译者注&#xff1a;本文翻译自Cormac的博客&#xff0c;并未严格地逐字逐句的直译&#xff0c;如有谬误&#xff0c;万望见谅。原文见此http://cormachogan.com/2015/09/14/step-by-step-deployment-of-the-vsan-witness-appliance/现在开始在之前的帖子中我曾经介绍过见证虚拟…

PyCharm编程环境的中英文字体分别设置的好处多----一石三鸟地解决中文字体不一致、英文字体不涵盖中文字符、编程字体实用性兼顾美观性的三个问题

在编程环境&#xff08;例如Python的PyCharm&#xff09;中&#xff0c;我们希望编程环境的字体具有如下特性&#xff1a; &#xff08;1&#xff09;字体覆盖中文和英文字符。 &#xff08;2&#xff09;等宽字体&#xff0c;并且是TrueType字体&#xff0c;方便辨识代码中缩…

WordPress博客系统的安全

随着计算机网络的流行&#xff0c;越来越多的人开始创建自己的博客&#xff0c;论起博客系统&#xff0c;全球用的最多的博客系统就是wordpress&#xff08;以下简称WP&#xff09;。但是如果用过WP的人都应该知道&#xff0c;WP的站点想要做的好看&#xff0c;插件是必不可少的…

mysql为什么行数据库_关系数据表中的行称为什么?

在一个二维表中&#xff0c;水平方向的行称为元组&#xff0c;每一行是一个元组&#xff1b;元组对应表中的一个具体记录。数据元组也称为记录。一个数据表中的每一个记录均有一个惟一的编号(记录号)。一个记录也就是数据表中的一行。元组(tuple)是关系数据库中的基本概念&…

maven安装以及eclipse配置maven

http://jingyan.baidu.com/article/295430f136e8e00c7e0050b9.html 必须先下载并安装JDK&#xff0c;配置JDK的环境变量JAVA_HOME&#xff0c;否则maven将无法使用 eclipse安装maven插件后必须重新定位maven到本地maven目录 如下定位&#xff1a; 为了使得Eclipse中安装的Maven…

JS 问题集锦

【1】js页面跳转 和 js打开新窗口方法 第一种&#xff1a;<script language"javascript" type"text/javascript">window.location.href"http://www.xlfun.com/login.php?backurl"window.location.href; </script>第二种&#xff1a…

重温Observer模式--热水器·改(转载)

引言 在 C#中的委托和事件 一文的后半部分&#xff0c;我向大家讲述了Observer(观察者)模式&#xff0c;并使用委托和事件实现了这个模式。实际上&#xff0c;不使用委托和事件&#xff0c;一样可以实现Observer模式。在本文中&#xff0c;我将使用GOF的经典方式&#xff0c;再…

龙图 VP 李翀:数据化运营及云计算下的运维

文 | 龙图 VP 李翀原文地址&#xff1a;当游戏遇上大数据和云计算——谈数据化运营及云计算下的运维龙图做了8年的游戏&#xff0c;真正快速发展起来是在移动互联网这个时代。随着刀塔快速的扩张&#xff0c;我们在各个领域都遇到了非常多的之前没有想到过的状态。发现云计算其…

鼠标移动时,光标相对于对象的位置

鼠标在一个物体上移动时&#xff0c;能够计算出光标相对于任何其它对象的相对位置。 Code<Grid x:Name"LayoutRoot" Background"White"> <Grid HorizontalAlignment"Left" VerticalAlignment"Top" Name"grid1&q…

怎么判断一个字符串的最长回文子串是否在头尾_【Leetcode每日打卡】最长回文串...

干货预警&#xff1a;所有文章都会首发于我的公众号【甜姨的奇妙冒险】&#xff0c;欢迎watch。一、来历&#xff1a;力扣从3月开始开启了每日一题打卡活动&#xff0c;于是跟风加入了打卡大军&#xff0c;这两天写评论、发题解&#xff0c;没想到反响还不错&#xff0c;收到了…

.NET平台下WEB应用程序的部署(安装数据库和自动配置)

.NET平台下WEB应用程序的部署(安装数据库和自动配置)李洪根在.NET平台下&#xff0c;部署 Web 解决方案是比较方便的。我们可以利用Visual Studio.NET 2003添加一个WEB安装项目&#xff0c;在部署的“文件系统编辑器”中添加项目的主输出和内容文件&#xff0c;非常简易地完成安…

苹果原壁纸高清_全面屏壁纸高清 | 电影经典台词截图高清

iPhonex手机壁纸高清(苹果xs壁纸&#xff0c;苹果xr壁纸&#xff0c;iPhone11壁纸&#xff0c;安卓全屏壁纸)火影壁纸高清&#xff0c;经典电影台词截图拼接壁纸&#xff0c;电影《去他妈的世界》壁纸&#xff0c;欧美电影截图加上经典台词&#xff0c;2020好看的手机壁纸&…

python字符串切片用法_详解Python字符串切片

在python中,我们定义好一个字符串,如下所示。 在python中定义个字符串然后把它赋值给一个变量。 我们可以通过下标访问单个的字符,跟所有的语言一样,下标从0开始(==,我自己都觉得写的好脑残了) 这个时候呢,我们可以通过切片的方式来截取出我们定义的字符串的一部分。 使用…

azkaban config: nodes:_关于Nordic SDK的sdk.config.h

使用MDK对Nordic SDK开发&#xff0c;离不开sdk.config.h。请看以下两个视图&#xff1a;Text Editor视图Configuration Wiard视图咋一看挺神奇的&#xff0c;配置视图话&#xff0c;方便。具体实现和规则就不一一介绍了&#xff0c;网页搜“MDK中Configuration Wiard的使用”。…

SilverLight开发系列第1步:搭建开发环境

来自 http://www.cnblogs.com/kaima/archive/2008/08/17/1269637.html 在缺乏SilverLight中文教程的今天&#xff0c;新人要入门不容易&#xff0c;所以我根据自己阅读英文原档和实践经验&#xff0c;总结一个系列。首先介绍的是开发环境的搭建。 个人强烈推荐安装英文版的开发…

php使用smtp.sina.com邮箱发送邮件

2019独角兽企业重金招聘Python工程师标准>>> 需要写一个smtp发送类 <?php set_time_limit(120);class smtp {/* Public Variables */var $smtp_port;var $time_out;var $host_name;var $log_file;var $relay_host;var $debug;var $auth;var $user;var $pass;var…

java 不存在就创建_Java 判断多级路径是否存在,不存在就创建

Java 判断多级路径是否存在&#xff0c;不存在就创建方案一&#xff1a;(带文件名的Path&#xff1a;如&#xff1a;D:\news\2014\12\abc.text)public boolean isexitsPath(String path)throws InterruptedException{String [] pathspath.split("\\\\");StringBuffer…