列出小于N的所有素数

普通计算方式, 校验每个数字

优化的几处:

  • 判断是否整除时, 除数使用小于自身的平方根的素数
  • 大于3的素数, 都在6的整数倍两侧, 即 6m - 1 和 6m + 1
public class DemoPrime {
private int[] primes;
private int max;
private int pos;
private int total; public DemoPrime(int max) {
this.max = max;
int length = max / 3;
primes = new int[length];
pos = 0;
total = 0;
} private void put(int prime) {
primes[pos] = prime;
if (pos < primes.length - 1) {
pos++;
} else {
throw new RuntimeException("Length exceed");
}
} private boolean isPrime(int num) {
int limit = (int)Math.sqrt(num);
for (int i = 0; i < pos; i++) {
if (primes[i] > limit) {
break;
}
total++;
if (num % primes[i] == 0) return false;
}
return true;
} public void calculate() {
put(2);
put(3);
int val = 1;
for (int i = 0; val <= max - 6;) {
val += 4;
if (isPrime(val)) {
put(val);
}
val += 2;
if (isPrime(val)) {
put(val);
}
}
System.out.println("Tried: " + total);
} public void print() {
System.out.println("Total: " + pos);
/*for (int i = 0; i < pos; i++) {
System.out.println(primes[i]);
}*/
} public static void main(String[] args) {
DemoPrime dp = new DemoPrime(10000000);
dp.calculate();
dp.print();
}
}

.使用数组填充的方式

一次性创建大小为N的int数组的方式, 在每得到一个素数时, 将其整数倍的下标(除自身以外)的元素都置位, 并且只需要遍历到N的平方根处. 最后未置位的元素即为素数, 在过程中可以统计素数个数. 这种方法比前一种效率高一个数量级.

public class DemoPrime2 {
private int[] cells;
private int max;
private int total; public DemoPrime2(int max) {
this.max = max;
cells = new int[max];
total = max;
} private void put(int prime) {
int i = prime + prime;
while (i < max) {
if (cells[i] == 0) {
cells[i] = 1;
total--;
}
i += prime;
}
} public void calculate() {
total -= 2; // Exclude 0 and 1
put(2);
put(3);
int limit = (int)Math.sqrt(max);
for (int i = 4; i <= limit; i++) {
if (cells[i] == 0) {
put(i);
}
}
} public void print() {
System.out.println("Total: " + total);
/*for (int i = 2; i < max; i++) {
if (cells[i] == 0) {
System.out.println(i);
}
}*/
} public static void main(String[] args) throws InterruptedException {
DemoPrime2 dp = new DemoPrime2(10000000);
Thread.sleep(1000L);
long ts = System.currentTimeMillis();
dp.calculate();
dp.print();
long elapse = System.currentTimeMillis() - ts;
System.out.println("Time: " + elapse);
}
}

.

判断大数是否为素数

Miller-Rabin算法

对于大数的素性判断,目前Miller-Rabin算法应用最广泛。一般底数仍然是随机选取,但当待测数不太大时,选择测试底数就有一些技巧了。比如,如果被测数小于4 759 123 141,那么只需要测试三个底数2, 7和61就足够了。当然,你测试的越多,正确的范围肯定也越大。如果你每次都用前7个素数(2, 3, 5, 7, 11, 13和17)进行测试,所有不超过341 550 071 728 320的数都是正确的。如果选用2, 3, 7, 61和24251作为底数,那么10^16内唯一的强伪素数为46 856 248 255 981。这样的一些结论使得Miller-Rabin算法在OI中非常实用。通常认为,Miller-Rabin素性测试的正确率可以令人接受,随机选取k个底数进行测试算法的失误率大概为4^(-k)。

Miller-Rabin算法是一个RP算法。RP是时间复杂度的一种,主要针对判定性问题。一个算法是RP算法表明它可以在多项式的时间里完成,对于答案为否定的情形能够准确做出判断,但同时它也有可能把对的判成错的(错误概率不能超过1/2)。RP算法是基于随机化的,因此多次运行该算法可以降低错误率。还有其它的素性测试算法也是概率型的,比如Solovay-Strassen算法.

AKS算法

AKS最关键的重要性在于它是第一个被发表的一般的、多项式的、确定性的和无仰赖的素数判定算法。先前的算法至多达到了其中三点,但从未达到全部四个。

  • AKS算法可以被用于检测任何一般的给定数字是否为素数。很多已知的高速判定算法只适用于满足特定条件的素数。例如,卢卡斯-莱默检验法仅对梅森素数适用,而Pépin测试仅对费马数适用。
  • 算法的最长运行时间可以被表为一个目标数字长度的多项式。ECPP和APR能够判断一个给定数字是否为素数,但无法对所有输入给出多项式时间范围。
  • 算法可以确定性地判断一个给定数字是否为素数。随机测试算法,例如米勒-拉宾检验和Baillie–PSW,可以在多项式时间内对给定数字进行校验,但只能给出概率性的结果。
  • AKS算法并未“仰赖”任何未证明猜想。一个反例是确定性米勒检验:该算法可以在多项式时间内对所有输入给出确定性结果,但其正确性却基于尚未被证明的广义黎曼猜想。

AKS算法的时间复杂度是 O(log(n)), 比Miller-Rabin要慢

/***************************************************************************
* Team
**************
* Arijit Banerjee
* Suchit Maindola
* Srikanth Manikarnike
*
**************
* This is am implementation of Agrawal–Kayal–Saxena primality test in java.
*
**************
* The algorithm is -
* 1. l <- log n
* 2. for i<-2 to l
* a. if an is a power fo l
* return COMPOSITE
* 3. r <- 2
* 4. while r < n
* a. if gcd( r, n) != 1
* return COMPSITE
* b. if sieve marked n as PRIME
* q <- largest factor (r-1)
* o < - r-1 / q
* k <- 4*sqrt(r) * l
* if q > k and n <= r
* return PRIME
* c. x = 2
* d. for a <- 1 to k
* if (x + a) ^n != x^n + mod (x^r - 1, n)
* return COMPOSITE
* e. return PRIME
*/ public class DemoAKS {
private int log;
private boolean sieveArray[];
private int SIEVE_ERATOS_SIZE = 100000000; /* aks constructor */
public DemoAKS(BigInteger input) {
sieveEratos(); boolean result = checkIsPrime(input); if (result) {
System.out.println("1");
} else {
System.out.println("0");
}
} /* function to check if a given number is prime or not */
public boolean checkIsPrime(BigInteger n) {
BigInteger lowR, powOf, x, leftH, rightH, fm, aBigNum;
int totR, quot, tm, aCounter, aLimit, divisor;
log = (int) logBigNum(n);
if (findPower(n, log)) {
return false;
}
lowR = new BigInteger("2");
x = lowR;
totR = lowR.intValue();
for (lowR = new BigInteger("2");
lowR.compareTo(n) < 0;
lowR = lowR.add(BigInteger.ONE)) {
if ((lowR.gcd(n)).compareTo(BigInteger.ONE) != 0) {
return false;
}
totR = lowR.intValue();
if (checkIsSievePrime(totR)) {
quot = largestFactor(totR - 1);
divisor = (int) (totR - 1) / quot;
tm = (int) (4 * (Math.sqrt(totR)) * log);
powOf = mPower(n, new BigInteger("" + divisor), lowR);
if (quot >= tm && (powOf.compareTo(BigInteger.ONE)) != 0) {
break;
}
}
}
fm = (mPower(x, lowR, n)).subtract(BigInteger.ONE);
aLimit = (int) (2 * Math.sqrt(totR) * log);
for (aCounter = 1; aCounter < aLimit; aCounter++) {
aBigNum = new BigInteger("" + aCounter);
leftH = (mPower(x.subtract(aBigNum), n, n)).mod(n);
rightH = (mPower(x, n, n).subtract(aBigNum)).mod(n);
if (leftH.compareTo(rightH) != 0) return false;
}
return true;
} /* function that computes the log of a big number*/
public double logBigNum(BigInteger bNum) {
String str;
int len;
double num1, num2;
str = "." + bNum.toString();
len = str.length() - 1;
num1 = Double.parseDouble(str);
num2 = Math.log10(num1) + len;
return num2;
} /*function that computes the log of a big number input in string format*/
public double logBigNum(String str) {
String s;
int len;
double num1, num2;
len = str.length();
s = "." + str;
num1 = Double.parseDouble(s);
num2 = Math.log10(num1) + len;
return num2;
} /* function to compute the largest factor of a number */
public int largestFactor(int num) {
int i;
i = num;
if (i == 1) return i;
while (i > 1) {
while (sieveArray[i] == true) {
i--;
}
if (num % i == 0) {
return i;
}
i--;
}
return num;
} /*function given a and b, computes if a is power of b */
public boolean findPowerOf(BigInteger bNum, int val) {
int l;
double len;
BigInteger low, high, mid, res;
low = new BigInteger("10");
high = new BigInteger("10");
len = (bNum.toString().length()) / val;
l = (int) Math.ceil(len);
low = low.pow(l - 1);
high = high.pow(l).subtract(BigInteger.ONE);
while (low.compareTo(high) <= 0) {
mid = low.add(high);
mid = mid.divide(new BigInteger("2"));
res = mid.pow(val);
if (res.compareTo(bNum) < 0) {
low = mid.add(BigInteger.ONE);
} else if (res.compareTo(bNum) > 0) {
high = mid.subtract(BigInteger.ONE);
} else if (res.compareTo(bNum) == 0) {
return true;
}
}
return false;
} /* creates a sieve array that maintains a table for COMPOSITE-ness
* or possibly PRIME state for all values less than SIEVE_ERATOS_SIZE
*/
public boolean checkIsSievePrime(int val) {
if (sieveArray[val] == false) {
return true;
} else {
return false;
}
} long mPower(long x, long y, long n) {
long m, p, z;
m = y;
p = 1;
z = x;
while (m > 0) {
while (m % 2 == 0) {
m = (long) m / 2;
z = (z * z) % n;
}
m = m - 1;
p = (p * z) % n;
}
return p;
} /* function, given a and b computes if a is a power of b */
boolean findPower(BigInteger n, int l) {
int i;
for (i = 2; i < l; i++) {
if (findPowerOf(n, i)) {
return true;
}
}
return false;
} BigInteger mPower(BigInteger x, BigInteger y, BigInteger n) {
BigInteger m, p, z, two;
m = y;
p = BigInteger.ONE;
z = x;
two = new BigInteger("2");
while (m.compareTo(BigInteger.ZERO) > 0) {
while (((m.mod(two)).compareTo(BigInteger.ZERO)) == 0) {
m = m.divide(two);
z = (z.multiply(z)).mod(n);
}
m = m.subtract(BigInteger.ONE);
p = (p.multiply(z)).mod(n);
}
return p;
} /* array to populate sieve array
* the sieve array looks like this
*
* y index -> 0 1 2 3 4 5 6 ... n
* x index 1
* | 2 T - T - T ...
* \/ 3 T - - T ...
* 4 T - - ...
* . T - ...
* . T ...
* n
*
*
*
*
*/
public void sieveEratos() {
int i, j;
sieveArray = new boolean[SIEVE_ERATOS_SIZE + 1];
sieveArray[1] = true;
for (i = 2; i * i <= SIEVE_ERATOS_SIZE; i++) {
if (!sieveArray[i]) {
for (j = i * i; j <= SIEVE_ERATOS_SIZE; j += i) {
sieveArray[j] = true;
}
}
}
} public static void main(String[] args) {
new DemoAKS(new BigInteger("100000217"));
}
}

  

N以内的素数计算(Java代码)的更多相关文章

  1. 求出100以内的素数(java实现)

    j package test1; //2018/11/30 //求100以内的所有素数 public class Main10 { public static void main(String[] a ...

  2. 蓝桥杯 ALGO-156 表达式计算 JAVA代码 栈的应用

     算法训练 表达式计算   时间限制:1.0s   内存限制:256.0MB      问题描述 输入一个只包含加减乖除和括号的合法表达式,求表达式的值.其中除表示整除. 输入格式 输入一行,包含一个 ...

  3. JAVA代码根据经纬度范围计算WGS84与谷歌全球墨卡托包含的切片数目与拼接图像像素尺寸

    根据项目需求编写的代码. 适用场景:在网络地图上,比如天地图与谷歌地图,用户用鼠标在地图上拉一个矩形框,希望下载该矩形框内某一层级的瓦片数据,并将所有瓦片拼接成一个完整的,包含地理坐标的tif图像. ...

  4. 在java代码中执行js脚本,实现计算出字符串“(1+2)*(1+3)”的结果

            今天在公司项目中,发现一个计算运费的妙招.由于运费规则各种各样,因此写一个公式存到数据库.下次需要计算运费时,直接取出这个公式,把公式的未知变量给替换掉,然后计算出结果就是ok了. 一 ...

  5. 用python计算100以内的素数

    用python计算100以内的素数 : break else: list.append(i)print(list)

  6. Java代码计算运行时间

    突然想准确的测试一下Java代码的执行时间,在网上找了一会.发现基本有以下两种方法:第一种是以毫秒为单位计算的. Java代码 //伪代码 long startTime=System.currentT ...

  7. JAVA代码:生成一个集合,自定义大小,100以内的随机整数

    JAVA代码:生成一个集合,自定义大小,100以内的随机整数 方法一:(Random类) package com.dawa.test; import java.util.ArrayList; impo ...

  8. 查找素数(0~1000)的算法(Java代码)

    1.一般方法,设置标兵,进行查找 class prime{ //检查是否是素数 public void isPrime(){ ; ;i<=;i++){ ; ;j<i;j++){ ){ co ...

  9. Java例题_27 100以内的素数

    1 /*27 [程序 27 求素数] 2 题目:求 100 之内的素数 3 */ 4 5 /*分析 6 * 素数:是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数. 7 * 同第二题: ...

随机推荐

  1. CspParameters 对象已存在异常 解决多应用对同一容器的访问问题

    CspParameters cspParams; cspParams = new CspParameters(PROVIDER_RSA_FULL); cspParams.KeyContainerNam ...

  2. Flask--登录验证(多个装饰器)

    登录验证(多个装饰器) from flask import Flask,url_for,session,render_template import functools app = Flask(__n ...

  3. Centos 脚本中几个特殊符号的作用笔记

    反斜杠(\):使反斜杠后面的一个变量变为单纯的字符串 单引号(''):转义其中所有的变量为单纯的字符串 双引号(""):保留其中的变量属性,不进行转义处理 反引号(``):把其中的 ...

  4. The Instruction Set In Cortex-M3

    The Cortex-M3 supports the Thumb-2 instruction set. This is one of the most important features of th ...

  5. C 是什么样的语言?

    学习交流可加 微信读者交流①群 (添加微信:coderAllen) 程序员技术QQ交流①群:736386324 --- ==C 是什么样的语言?== 这个问题不要急于寻找问题的答案,而是应该先去考虑当 ...

  6. Codeforces G. Bus Number(dfs排列)

    题目描述: Bus Number time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  7. CentOS7:sorry,that didn't work.please try again!

    参考以下解决方案,重点是vi etc/selinux/config 把 enforcing 改为 disable 应用场景 linux管理员忘记root密码,需要进行找回操作.注意事项:本文基于cen ...

  8. 通过jekyll在Github 搭建个人博客

    能快乐旅行的人,一定是轻装旅行的人 前言 应广大的网友(装逼~~哈哈)要求,决定写个Jekyll+Giuhub搭建博客的教程,以便帮助更多的人,毕竟我也是这么过来的.这是我的博客地址,可以先看看效果. ...

  9. 2019.12.10 break 标记

    class Demo01{ public static void main(String[] args) { int i=0; a:for(i=0;i<3;i++){ for(int j=0;j ...

  10. zeptojs库

    一.简介 ①Zepto是一个轻量级的针对现代高级浏览器的JavaScript库, 它与jquery有着类似的api. ②Zepto的设计目的是提供 jQuery 的类似的API,但并不是100%覆盖 ...