搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
IT小白
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
雨林木风系统封装工具封装xp_Windows 这样定制自己的系统映像,重装便捷又省时...
2
深入理解volatile的三大特性----------简单易懂
3
Elasticsearch_elasticsearch 数据集
4
正则表达式-限定位数的正数_正则表达式限制位数
5
git 提交代码规范总结_git 修改代码使用stylem
6
softether 使用方法_什么是重装系统?工控机重装系统的几种方法
7
若依源码解析:RuoYi-Vue登录和鉴权的实现_若依后端鉴权
8
小米电脑管家安装教程_小米电脑管家怎么安装
9
Windows系统安装Java环境_windows安装java环境
10
【启发式算法】Python实现禁忌搜索算法求解TSP问题
当前位置:
article
> 正文
求解素数几种方法_素数的求解
作者:IT小白 | 2024-02-10 19:18:10
赞
踩
素数的求解
转贴文章请注明:逸学堂
求解一个算法,我们首先要知道它的数学含义.依据这个原则,首先我们要知道什么是素数.; 素数是这样的整数,它除了表示为它自己和1的乘积以外,无论他表示为任何两个整数的乘积。
找素数的方法多种多样。
1:是从2开始用“是则留下,不是则去掉”的方法把所有的数列出来(一直列到你不想再往下列为止,比方说,一直列到10,000)。第一个数是2,它是一个素数,所以应当把它留下来,然后继续往下数,每隔一个数删去一个数,这样就能把所有能被2整除、因而不是素数的数都去掉。在留下的最小的数当中,排在2后面的是3,这是第二个素数,因此应该把它留下,然后从它开始往后数,每隔两个数删去一个,这样就能把所有能被3整除的数全都去掉。下一个未去掉的数是5,然后往后每隔4个数删去一个,以除去所有能被5整除的数。再下一个数是7,往后每隔6个数删去一个;再下一个数是11,往后每隔10个数删一个;再下一个是13,往后每隔12个数删一个。就这样依法做下去。
但是编程我们一般不采用上面的方法,并不说这中方法计算机实现不了,或者说实现算法比较复杂。因为它更像一个数学推理。最后我们也给一个算法。
下面我们介绍几种长用的编程方法。
2:
遍历2以上N的平方根以下的每一个整数,是不是能整除N
;(
这是最基本的方法)
3
:遍历2以上N的平方根以下的每一个素数,是不是能整除N
;(
这个方法是上面方法的改进,但要求
N
平方根以下的素数已全部知道
)
4
:采用
Rabin-Miller
算法进行验算;
例如:N
=
2
^
127
-
1是一个38位数,要验证它是否为素数,用上面几个不同的方法:
验算结果,假设计算机能每秒钟计算1亿次除法,那么
算法
2
要用4136年,算法
3
要用93年,算法
4
只要不到1秒钟!
(
这些数据是通过计算得到
)
另外印度有人宣称素数测试是
P
问题,我一直没有找到那篇论文,听说里面有很多数学理论。如果那位大人有这篇论文,麻烦转发一份(
E-Mail:exuetang@126.com
)有任何问题也可以写信与我讨论。
下面我们分别实现上面的三种算法:
以下算法我们不涉及内存溢出,以及大数字的问题。如果测试数字超过2^32,发生内存溢出,你需要自己使用策略解决这个问题,在这里只讨论32位机有效数字算法。
1
:
//
算法0:是从2开始用“是则留下,不是则去掉”的方法把所有的数列出来
//
最后数组中不为0的数字就是要查找的素数。
void
PrimeNumber0()
{
// int time ::GetTickCount();
// cout << "start time:" << time << endl;
int
Max[MAX_NUMBER];
//
在栈上分配,栈上空间要求一般都在2M之间,
//
如果你需要更大空间,请在堆上申请空间(就是通过malloc,new来申请).
memset(Max,0,MAX_NUMBER);
for
(
int
i = 0 ; i < MAX_NUMBER; ++i)
{
Max[i] = i;
}
int
cout = 0;
//
记录当前i的位置
//
遍历整个数组
for
(i = 1; i < MAX_NUMBER; ++i)
{
if
(Max[i] != 0 )
//
如果数据不为0,说明是一个素数
{
int
iCout = i;
int
j = Max[i];
//
记录数组中数组位的数字,以便设置
while
((iCout+=j) < MAX_NUMBER)
{
//
把不是素数的数位在数组中置为0
Max[iCout] = 0;
}
++cout;
}
}
// int time ::GetTickCount();
// cout << "end time:" << time << endl;
}
2
:这个算法可以修改成为,验证一个给定数字是否是一个素数。
//
因为我们讨论多个算法,所以我们把每个算法都单独
//
写在一个或多个函数内。这些函数并不要求输入值和返回值
//
如果你需要这些结果,可以自己修改。
//
算法1:遍历2以上N的平方根以下的每一个整数,是不是能整除N;
void
PrimeNumber1()
{
// int time ::GetTickCount();
// cout << "start time:" << time << endl;
int
Max[MAX_NUMBER/2];
//
在栈上分配,栈上空间要求一般都在2M之间,
//
如果你需要更大空间,请在堆上申请空间(就是通过malloc,new来申请).素数的个数很少
//
所以没有必要申请和所求数字同样大小的空间。
memset(Max,0,MAX_NUMBER);
Max[0] = 2;
//
放入第一个素数,有人说2不是素数,如果你是其中一员,就改成3吧
int
cout = 1;
//
记录素数个数
//
挨个数进行验证
bool
bflag =
true
;
for
(
int
i = 3; i < MAX_NUMBER; ++i)
{
bflag =
true
;
//
需要是使用数学库(math.h)中sqrt
int
iTemp = (
int
)sqrt((
float
)i);
//
强制转换成int类型,有的人在这里使用i+1就是为了增加sqrt的精度
//
没有特殊函数,你也可以使用int iTemp = (int)sqrt(i)+1;来提高进度
for
(
int
j = 2; j < iTemp; ++j)
{
if
(i%j == 0)
//
求余,如果为0说明,可以整除,不是素数。
{
bflag =
false
;
break
;
}
}
//
经过验证是素数,放入数组。
if
(bflag)
{
Max[cout++] = i;
}
}
// int time ::GetTickCount();
// cout << "end time:" << time << endl;
}
3
:这个方法是上面方法的改进,但要求N平方根以下的素数已全部知道
//
算法2:遍历2以上N的平方根以下的每一个素数,是不是能整除N;
// (
这个方法是上面方法的改进,但要求N平方根以下的素数已全部知道)
void
PrimeNumber2()
{
// int time ::GetTickCount();
// cout << "start time:" << time << endl;
int
Max[MAX_NUMBER/2];
//
在栈上分配,栈上空间要求一般都在2M之间,
//
如果你需要更大空间,请在堆上申请空间(就是通过malloc,new来申请).素数的个数很少
//
所以没有必要申请和所求数字同样大小的空间。
memset(Max,0,MAX_NUMBER);
Max[0] = 2;
//
放入第一个素数,有人说2不是素数,如果你是其中一员,就改成3吧
int
cout = 1;
//
记录素数个数
//
挨个数进行验证
bool
bflag =
true
;
for
(
int
i = 3; i < MAX_NUMBER; ++i)
{
bflag =
true
;
//
需要是使用数学库(math.h)中sqrt
int
iTemp = (
int
)sqrt((
float
)i);
//
强制转换成int类型,有的人在这里使用i+1就是为了增加sqrt的精度
//
没有特殊函数,你也可以使用int iTemp = (int)sqrt(i)+1;来提高进度
/
//
修改的是这里以下的部分
for
(
int
j = 0; j < cout; ++j)
{
if
(i%Max[j] == 0)
//
求余,如果为0说明,可以整除,不是素数。
{
bflag =
false
;
break
;
}
}
//
修改的是这里以上的部分
//
//
经过验证是素数,放入数组。
if
(bflag)
{
Max[cout++] = i;
}
}
// int time ::GetTickCount();
// cout << "end time:" << time << endl;
}
4
:
采用
Rabin-Miller
算法进行验算,
Rabin-Miller
算法是典型的验证一个数字是否为素数的方法。
判断素数的方法是Rabin-Miller概率测试,那么他具体的流程是什么呢。假设我们要判断n是不是素数,首先我们必须保证n 是个奇数,那么我们就可以把n 表示为 n = (2^r)*s+1,注意s 也必须是一个奇数。然后我们就要选择一个随机的整数a (1<=a<=n-1),接下来我们就是要判断 a^s=1 (mod n) 或a^((2^j)*s)= -1(mod n)(0<=j<R),如果任意一式成立,我们就说n通过了测试,但是有可能不是素数也能通过测试。所以我们通常要做多次这样的测试,以确保我们得到的是一个素数。(DDS的标准是要经过50次测试)
//
算法3:采用Rabin-Miller算法进行验算
//
首先选择一个代测的随机数p,计算b,b是2整除p-1的次数。然后计算m,使得n=1+(2^b)m。
//
(1) 选择一个小于p的随机数a。
//
(2) 设j=0且z=a^m mod p
//
(3) 如果z=1或z=p-1,那麽p通过测试,可能使素数
//
(4) 如果j>0且z=1, 那麽p不是素数
//
(5) 设j=j+1。如果j<b且z<>p-1,设z=z^2 mod p,然后回到(4)。如果z=p-1,那麽p通过测试,可能为素数。
//
(6) 如果j=b 且z<>p-1,不是素数
//
判定是否存在 a^s=1 (mod n) 或a^((2^j)*s)= -1(mod n)(0<=j<R),
bool
Witness(
int
a,
int
n)
{
//
解释一下数学词汇:
// ceil
求不小于x的最小整数,函数原型extern float ceil(float x);求得i的最大值
// log
计算x的自然对数,函数原型extern float log(float x);
long
i,d=1,x;
for
(i=(
int
)ceil(log((
double
)n-1)/log(2.0))-1;i>=0;--i)
{
x=d;
d=(d*d)%n;
if
((1==d) && (x!=1) && (x!=n-1))
{
return
1;
}
if
((n-1)&(1<0))
{
d=(d*a)%n;
}
}
return
(d!=1);
}
//
参数n,是要测定的数字,s是要内部测试的次数。
bool
Rabin_Miller(
int
n,
int
s)
{
for
(
int
j = 0;j < s; ++j)
{
int
a = rand()*(n-2)/RAND_MAX + 1;
//
获得一个随机数1<=a<=n-1
if
(Witness(a,n))
//
利用这个随即数和n进行判断对比,只要有一次返回true,就说明n不是一个素数
{
return
false
;
}
}
return
true
;
//
通过验证是一个素数
}
//
算法3:采用Rabin-Miller算法进行验算
//
这个算法是求大素数使用的。所以你的必须想办法支持大数字运算,
//
不然极易造成内存访问失效,我在我的机子上,MAX_NUMBER=10000时就会出现问题,1000就没有问题
void
PrimeNumber3()
{
int
Max[MAX_NUMBER/2];
//
在栈上分配,栈上空间要求一般都在2M之间,
//
如果你需要更大空间,请在堆上申请空间(就是通过malloc,new来申请).素数的个数很少
//
所以没有必要申请和所求数字同样大小的空间。
int
cout = 0;
//
记录素数个数
memset(Max,0,MAX_NUMBER/2);
for
(
int
i = 2; i < 1000; ++i)
{
if
(Rabin_Miller(i,20))
{
Max[cout++] = i;
}
}
}
以上程序都经过测试,测试环境Window 2003+VC7.1
小结:以上只是简单介绍一下求素数的几种常用方法,实际方法远远不知这些。对于普通用户来说算法2就可以方便应用了。Rabin-miller算法,确实很高效,但是如果你对数学,编程知识不是很熟悉,建议不要使用。
如果使用过程中有任何疑问请与我联系。
QQ
:35091551
MSN
:
ugg_xchj@163.com
下载源文件
http://www.exuetang.net/article/NewsViewAdmin.aspx?NewsId=191
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/IT小白/article/detail/75216
推荐阅读
article
linux
下
显卡
优化
,[转载]
Linux
下
NVIDIA
显卡
闭源
驱动
的
一些
优化
...
完全搬运,原文请猛戳
NVIDIA
对开源
驱动
开发
的
支持之差从 Linus Torvalds 那句著名
的
“FuckNVID...
赞
踩
article
STM32
使用
PWM
实现
led
亮度
变化_
stm32
控制
led
亮度
...
stm32
使用
PWM
波实现
led
亮度
变化。_
stm32
控制
led
亮度
stm32
控制
led
亮度
...
赞
踩
article
PyQt
中使用
图像
资源
和管理
资源
文件_
pyqt
designer
如何将图片添加到
资源
...
在弹出的对话框中输入
资源
文件的名称,例如"resources",然后点击"Next",最后点击"Finish"完成创建。...
赞
踩
article
Ubuntu18.04
LTS
版本,实现
python
脚本
每天
定时
启动
_
ubuntu
定时
任务 执行p...
Ubuntu18.04
LTS
版本,实现
python
脚本
每天
定时
启动
_
ubuntu
定时
任务 执行
python
脚本
ubu...
赞
踩
article
视觉
检测
系统
:工厂生产
零部件
的智能
检测
...
通过这种方式,
系统
能够以高精度、高速度和非接触的方式对产品进行
检测
,从而实现对
零部件
表面缺陷的
检测
。该
系统
使用快速、精确...
赞
踩
article
探秘
文心
千帆
:
开发者
的大
模型
之旅与应用创新_文星
千帆
数据
导入...
它强调了遵守法律法规的重要性,提到了设计和实施
数据
保护措施,强调了对敏感
数据
的保护还提到了
数据
访问控制的重要性,强调了建...
赞
踩
article
linux
下查看过去
一段时间
内
系统
资源
使用
情况
_
linux
列出
一段时间
的
资源
占用
情况
...
sar命令可以做到:http://www.chinaz.com/server/2013/0401/297942.shtm...
赞
踩
article
ubuntu
/
linux
系统知识(21)
Ubuntu
22.04
个性化配置
dock
(
应用程序
启动栏...
在本文中,我们将向您展示一些在
Ubuntu
22.04
Jammy Jellyfish Linux 上的默认 GNOME...
赞
踩
article
Manjaro
安装
及调校笔记_
yaourt
安装
manjaro
...
1.
安装
注:SSD+HDD双硬盘下,已
安装
win10系统win10下使用rufus软件以DD镜像模式写入
安装
镜像在bi...
赞
踩
article
常用的
gnome
shell
扩展...
usertheme 启用后可自定义
shell
主题dash-to-dock dock设置unite 将左下角通知栏融入顶部...
赞
踩
article
STM32
的
ADC
电压采集...
时间记录:2024/2/9。
STM32
的
ADC
电压采集 时间记录...
赞
踩
article
panda
s使用sql
GROUP
_
CONCAT方法
_
panda
实现
group
_
concat
...
# 方法一 transform 单字段 (性能佳)df[df['付款方式']=='支付宝'][['付款人电话','被保险...
赞
踩
article
ArchLinux 更换
系统
语言
安装
搜狗
输入法
_
archlinux
安装
搜狗
输入法
...
建议新用户在
安装
Arch的时候先使用英文的
系统
环境,等稍微有了一定的使用经验之后再更换成中文环境,毕竟目前arch相关的...
赞
踩
article
【嵌入式】使用
STM32
实现
OLED
屏显_如何使用
stm32
指南者
led
显示
学号
姓名
...
目录实验目的:
显示
自己的学号和
姓名
。
显示
AHT20的温度和湿度。上下或左右的滑动
显示
长字符。_如何使用
stm32
指南者l...
赞
踩
article
win
python
怎么创建一个独立
的
进程
_
python
实现在
win
dows服务中新建
进程
的
方法...
本文实例讲述了
python
实现在
win
dows服务中新建
进程
的
方法。分享给大家供大家参考。具体实现方法如下:需要安装
的
软...
赞
踩
article
s3c2440
linux3.0下
PWM
使用之
蜂鸣器
驱动移植
_
pwm
-
beeper
...
这篇文档拖了好久了,都有点淡忘了。这段时间考试加实验太忙了,但还是先粗略的记录,总结下吧。先贴上修改过的地方。文件:ma...
赞
踩
article
sgu
题目分类_
nextprime
能
逆
推
吗...
以下分类收集于网络:动态规划
sgu
104
sgu
168
sgu
116(结合筛法的背包)
sgu
132(状态压缩dp)数学
sgu
...
赞
踩
article
Arch
Linux
配置
gnome
桌面_
arch
gnome
怎么设置
dock
...
Arch
Linux
安装完
gnome
桌面后,一般还需要配置好软件仓库环境(如AUR助手工具PARU),并需要进行进一步个...
赞
踩
article
Cython
0.15,
用
OpenMP
并行
多核加速
Python
!...
赖勇浩(http://laiyonghao.com)注:0、读懂这篇文章需要了解
OpenMP
基本
用
法。1、读懂这篇文...
赞
踩
article
docker
-
compose
学习:通过
image
指令指定
镜像
搭建一个简单
LNMP
_
docker
...
1、 安装
docker
-
compose
官网https://docs.
docker
.com/
compose
/一个不错的入...
赞
踩
相关标签
linux 下显卡优化
stm32
单片机
嵌入式硬件
pyqt
数据库
服务器
Python
python
ubuntu
自动化
视觉检测
文心千帆
文心一言
百度
linux
运维
Manjaro
Linux
shell
操作系统
ADC
sql
database