• 全部
  • 问答

自认是算法高手的进来

darcy07 2001-07-11 10:16:23
如何判断一个数是素数?
...全文
100 点赞 收藏 14
写回复
14 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
one_add_one 2001-07-17
写个QBASIC的程序:

DEFINT A-Z
CLS
PRINT 2;
FOR a = 3 TO 30000 STEP 2
t = 1
FOR b = 3 TO SQR(a) STEP 2
IF a MOD b = 0 THEN t = 0: EXIT FOR
NEXT
IF t = 1 THEN PRINT a;
NEXT

回复
yug 2001-07-15
这类算法很多嘛
回复
tansoul 2001-07-15
这样的问题,好象课本里有很多呀!
回复
WQ 2001-07-15
如何产生素数

Solovag-Strasson
Robert Solovag和Volker Strasson开发了一种概率的基本测试算法。这个算法使用了雅可比函数来测试p是否为素数:

(1) 选择一个小于p的随机数a。
(2) 如果GCD(a,p)<>1,那么p通不过测试,它是合数。
(3) 计算j=a^(p-1)/2 mod p。
(4) 计算雅可比符号J(a,p)。
(5) 如果j<>J(a,p),那么p肯定不是素数。
(6) 如果j=J(a,p),那麽p不是素数的可能性值多是50%

数a被称为一个证据,如果a不能确定p,p肯定不是素数。如果p是合数。随机数a是证据的概率不小于50%。对a选择t个不同的随机值,重复t次这种测试。p通过所有t次测试后,它是合数的可能性不超过1/2^t。

Lehmann
另一种更简单的测试是由Lehmann独自研究的。下面是它的测试算法:

(1) 选择一个小于p的随机数a。
(2) 计算a^(p-1)/2 mod p
(3) 如果a^(p-1)/2<>1或-1(mod p),那么p肯定不是素数。
(4) 如果a^(p-1)/2=1或-1(mod p),那麽p不是素数的可能性值多是50%

同样,重复t次,那麽p可能是素数所冒的错误风险不超过1/2^t。

Rabin-Miller
这是个很容易且广泛使用的简单算法,它基于Gary Miller的部分象法,有Michael Rabin发展。事实上,这是在NIST的DSS建议中推荐的算法的一个简化版。

首先选择一个代测的随机数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被当成证据的概率为75%。这意味着当迭代次数为t时,它产生一个假的素数所花费的时间不超过1/4^t。实际上,对大多数随机数,几乎99.99%肯定a是证据。

实际考虑:
在实际算法,产生素数是很快的。

(1) 产生一个n-位的随机数p
(2) 设高位和低位为1(设高位是为了保证位数,设低位是为了保证位奇数)
(3) 检查以确保p不能被任何小素数整除:如3,5,7,11等等。有效的方法是测试小于2000的素数。使用字轮方法更快
(4) 对某随机数a运行Rabin-Miller检测,如果p通过,则另外产生一个随机数a,在测试。选取较小的a值,以保证速度。做5次 Rabin-Miller测试如果p在其中失败,从新产生p,再测试。


在Sparc II上实现: 2 .8秒产生一个256位的素数
24.0秒产生一个512位的素数
2分钟产生一个768位的素数
5.1分钟产生一个1024位的素数


回复
WQ 2001-07-15
www.cfan2000.com
回复
darcy07 2001-07-11
N是否为素数,不能被小于 SQRT(N) 的所有素数整除。
这种方法太慢了,如果数太大且多的时候
回复
Muf 2001-07-11
一个简单的算法:
(注 SQRT 开平方)

N是否为素数,不能被小于 SQRT(N) 的所有素数整除。
回复
iamxia 2001-07-11
根据素数定义不就成了:只能被1和它本身整除。
回复
clavy 2001-07-11
这是什么样的高手啊.

不过现在有一些素数被称为"工业素数", 就是它不是素数的概率很小, 但不能证明它就是素数。有很多这样的算法, 俺还没有研究过的.
回复
anjun 2001-07-11
一个素数可以化成两个比他小的素数之积加一
你去试试吧
回复
林仪明 2001-07-11
老掉牙
回复
skymost 2001-07-11
太弱
回复
starfish 2001-07-11
呵呵,Alert抢我的生意呀:)
回复
Arter 2001-07-11
1)wilson定理:
p是素数的充要条件是:(p-1)! mod p=-1.
2)Robert Solovang & Volker Strassen 的概率测试法。
3)Lehmann 法(基以概率)。
4)Rabin-Miller 法
(斑竹starfish的网站上有代码!)
http://algorithm.126.com/

以下是由starfish(海星)提供的:
{=== 欧几里德算法求a,b的最大公倍数 ===}
function euclid(a,b:longint):longint;
begin
if b=0 then euclid:=a
else eucild:=euclid(b,a mod b);
end;


{=== 扩展的欧几里德算法,求出gcd(a,b)和满足gcd(a,b)=ax+by的整数x和y ===}
function extended_euclid(a,b:longint;var x,y:longint):longint;
var
t:longint;
begin
if b=0 then
begin
result:=a;
x:=1;
y:=0;
end
else
begin
result:=extended_euclid(b,a mod b,x,y);
t:=x;
x:=y;
y:=t-(a div b)*y;
end;
end;

{=== 求解模线性方程 ax ≡ b (mod n) 其中n>0 ===}
procedure modular_linear_equation_solver(a,b,n:longint);
var
d,x,y,e,i:longint;
begin
d:=extended_euclid(a,n,x,y);
if b mod d>0 then
writeln('No answer!') {输出无解信息}
else
begin
e:=x*(b div d)mod n;
for i:=0 to d-1 do
writeln( (e+i*(n div d)) mod n ); {输出第i个解 }
end;
end;


{==================================

求解模线性方程组(中国余数定理):

a ≡ B[1] (mod W[1])
a ≡ B[2] (mod W[2])
..........
a ≡ B[k] (mod W[k])

其中W,B已知,W[i]>0且W[i]与W[j]互质,
求a.

===================================}


function China(var B,W:array[1..k] of longint):longint;
var
i,d,x,y,a,m,n:longint;
begin
n:=1;
for i:=1 to k do
n:=n*W[i];
a:=0;
for i:=1 to k do
begin
m:=n div W[i];
d:=extended_euclid(W[i],m,x,y);
a:=(a+y*m*B[i])mod n;
end;
if a>0 then China:=a
else China:=a+n;
end;

{====================================================

返回x用二进制表示的长度,例如x=1011010,则返回7

====================================================}

function Binary_Length(x:integer):integer;
begin
result:=0;
while x>0 do
begin
inc(result);
x:=x shr 1;
end;
end;


{===============================

模取幂运算
计算a^b mod n

用到的Binary_Length可在前文找到

================================}
function Modular_Exponentiation(a,b,n:integer):integer;
var
c,i:integer;

begin
c:=0;
result:=1;
for i:=Binary_Length(b)-1 downto 0 do
begin
c:=c*2;
result:=(result*result) mod n;
if (b and (1 shl i))>0 then {if b[i]=1 then... }
begin
inc(c);
result:=(result*a) mod n;
end;
end;
end;


{=====================================

Miller-Rabin随机性素数测试算法

说明:
这种算法很快,但是有很小的概率会出错;
对于任意奇数n>2和正整数s,该算法的出错
概率至多为2^(-s),因此,增大s可以减小
出错概率,一般取s=50就足够了。


=====================================}

{用到的Binary_Length可在前文找到}
function Witness(a,n:integer):boolean;
var
i,d,x:integer;
begin
d:=1;
for i:=Binary_Length(n-1)-1 downto 0 do
begin
x:=d;
d:=(d*d) mod n;
if (d=1)and(x<>1)and(x<>n-1) then begin result:=true;exit;end;
if ((n-1) and (1 shl i))>0 then d:=(d*a) mod n; {if b[i]=1 then... ,其中b[i]是n-1的二进制的第i+1位}
end;
if d<>1 then result:=true
else result:=false;
end;

{ 在调用此函数之前记着要调用 randomize}
function Miller_Rabin(n,s:integer):boolean; {n为待测试的整数,n为素数则返回true;s为出错概率控制参数;}
var
j,a:integer;
begin
for j:=1 to s do
begin
a:=random(n-2)+1;
if Witness(a,n) then begin result:=false; exit;end; {n为合数,可以肯定}
end;
result:=true; {n为素数,只要s足够大,几乎可以肯定}
end;



回复
相关推荐
发帖
数据结构与算法
创建于2007-08-27

3.2w+

社区成员

数据结构与算法相关内容讨论专区
申请成为版主
帖子事件
创建了帖子
2001-07-11 10:16
社区公告
暂无公告