自然数 素数 质数_在Java中获取素数的无限列表

自然数 素数 质数

一个常见的问题是确定数字的素因式分解。 蛮力方法是审判部门( 维基百科 , 可汗学院 ),但是如果必须考虑多个数字,这需要大量的浪费工作。

一种广泛使用的解决方案是Eratosthenes筛( 维基百科 , 数学世界 )。 容易修改Eratosthenes的筛网以使其包含每个复合数的最大素数。 这使得随后计算数字的素因式分解非常便宜。

如果我们只关心素数,则可以使用带有Eratosthenes筛子的位图,也可以使用Atkin筛子( )。

(旁注:为清楚起见,我忽略了素数始终为“ 1 mod 2,n> 2”和“ 1或5 mod 6,n> 5”这一事实所引起的常见优化。这可以大大减少筛子所需的内存量。)

public enum SieveOfEratosthenes {SIEVE;private int[] sieve;private SieveOfEratosthenes() {// initialize with first million primes - 15485865// initialize with first 10k primes - 104729sieve = initialize(104729);}/*** Initialize the sieve.*/private int[] initialize(int sieveSize) {long sqrt = Math.round(Math.ceil(Math.sqrt(sieveSize)));long actualSieveSize = (int) (sqrt * sqrt);// data is initialized to zeroint[] sieve = new int[actualSieveSize];for (int x = 2; x < sqrt; x++) {if (sieve[x] == 0) {for (int y = 2 * x; y < actualSieveSize; y += x) {sieve[y] = x;}}}return sieve;}/*** Is this a prime number?** @FIXME handle n >= sieve.length!* * @param n* @return true if prime* @throws IllegalArgumentException*             if negative number*/public boolean isPrime(int n) {if (n < 0) {throw new IllegalArgumentException("value must be non-zero");}boolean isPrime = sieve[n] == 0;return isPrime;}/*** Factorize a number** @FIXME handle n >= sieve.length!* * @param n* @return map of prime divisors (key) and exponent(value)* @throws IllegalArgumentException*             if negative number*/private Map<Integer, Integer> factorize(int n) {if (n < 0) {throw new IllegalArgumentException("value must be non-zero");}final Map<Integer, Integer> factors = new TreeMap<Integer, Integer>();for (int factor = sieve[n]; factor > 0; factor = sieve[n]) {if (factors.containsKey(factor)) {factors.put(factor, 1 + factors.get(factor));} else {factors.put(factor, 1);}n /= factor;}// must add final termif (factors.containsKey(n)) {factors.put(n, 1 + factors.get(n));} else {factors.put(n, 1);}return factors;}/*** Convert a factorization to a human-friendly string. The format is a* comma-delimited list where each element is either a prime number p (as* "p"), or the nth power of a prime number as "p^n".* * @param factors*            factorization* @return string representation of factorization.* @throws IllegalArgumentException*             if negative number*/public String toString(Map factors) {StringBuilder sb = new StringBuilder(20);for (Map.Entry entry : factors.entrySet()) {sb.append(", ");if (entry.getValue() == 1) {sb.append(String.valueOf(entry.getKey()));} else {sb.append(String.valueOf(entry.getKey()));sb.append("^");sb.append(String.valueOf(entry.getValue()));}}return sb.substring(2);}
}

该代码有一个主要弱点-如果请求的数字超出范围,它将失败。 有一个简单的解决方法–我们可以根据需要动态调整筛子的大小。 我们使用Lock来确保多线程调用不会使筛选器处于中间状态。 我们需要注意避免在读锁和写锁之间陷入僵局。

private final ReadWriteLock lock = new ReentrantReadWriteLock();/*** Initialize the sieve. This method is called when it is necessary to grow* the sieve.*/private void reinitialize(int n) {try {lock.writeLock().lock();// allocate 50% more than required to minimize thrashing.initialize((3 * n) / 2);} finally {lock.writeLock().unlock();}}/*** Is this a prime number?* * @param n* @return true if prime* @throws IllegalArgumentException*             if negative number*/public boolean isPrime(int n) {if (n < 0) {throw new IllegalArgumentException("value must be non-zero");}if (n > sieve.length) {reinitialize(n);}boolean isPrime = false;try {lock.readLock().lock();isPrime = sieve[n] == 0;} finally {lock.readLock().unlock();}return isPrime;}/*** Factorize a number* * @param n* @return map of prime divisors (key) and exponent(value)* @throws IllegalArgumentException*             if negative number*/private Map<Integer, Integer> factorize(int n) {if (n < 0) {throw new IllegalArgumentException("value must be non-zero");}final Map<Integer, Integer> factors = new TreeMap<Integer, Integer>();try {if (n > sieve.length) {reinitialize(n);}lock.readLock().lock();for (int factor = sieve[n]; factor > 0; factor = sieve[n]) {if (factors.containsKey(factor)) {factors.put(factor, 1 + factors.get(factor));} else {factors.put(factor, 1);}n /= factor;}} finally {lock.readLock().unlock();}// must add final termif (factors.containsKey(n)) {factors.put(n, 1 + factors.get(n));} else {factors.put(n, 1);}return factors;}

Iterable <Integer>和foreach循环

在现实世界中,使用foreach循环(或显式Iterator)通常比逐项探查表要容易得多。 幸运的是,创建一个迭代器很容易,该迭代器建立在我们的自增长筛子上。

/*** @see java.util.List#get(int)** We can use a cache of the first few (1000? 10,000?) primes* for improved performance.** @param n* @return nth prime (starting with 2)* @throws IllegalArgumentException*             if negative number*/public Integer get(int n) {if (n < 0) {throw new IllegalArgumentException("value must be non-zero");}Iterator<Integer> iter = iterator();for (int i = 0; i < n; i++) {iter.next();}return iter.next();}/*** @see java.util.List#indexOf(java.lang.Object)*/public int indexOf(Integer n) {if (!isPrime(n)) {return -1;}int index = 0;for (int i : sieve) {if (i == n) {return index;}index++;}return -1;}/*** @see java.lang.Iterable#iterator()*/public Iterator<Integer> iterator() {return new EratosthenesListIterator();}public ListIterator<Integer> listIterator() {return new EratosthenesListIterator();}/*** List iterator.** @author Bear Giles <bgiles@coyotesong.com>*/static class EratosthenesListIterator extends AbstractListIterator<Integer> {int offset = 2;/*** @see com.invariantproperties.projecteuler.AbstractListIterator#getNext()*/@Overrideprotected Integer getNext() {while (true) {offset++;if (SIEVE.isPrime(offset)) {return offset;}}// we'll always find a value since we dynamically resize the sieve.}/*** @see com.invariantproperties.projecteuler.AbstractListIterator#getPrevious()*/@Overrideprotected Integer getPrevious() {while (offset > 0) {offset--;if (SIEVE.isPrime(offset)) {return offset;}}// we only get here if something went horribly wrongthrow new NoSuchElementException();}}
}

重要提示:代码:

for (int prime : SieveOfEratosthenes.SIEVE) { ... }

本质上是一个无限循环。 仅当JVM在分配新的筛选器时耗尽堆空间时,它才会停止。

实际上,这意味着我们可以在筛子中保持的最大质数约为1 GB。 这需要4 GB和4字节的整数。 如果我们只关心素数并使用常见的优化,则4 GB可以保存有关64 GB值的信息。 为简单起见,我们可以将其称为9到10位数字(以10为基数)。

如果将筛子放在磁盘上怎么办?

没有理由将筛子保留在内存中。 我们的迭代器可以从磁盘而不是内存缓存中安静地加载值。 一个4 TB的磁盘(可能是在原始模式下访问的)似乎将我们的筛子的大小提高到14到15位数字(以10为基数)。 实际上,它会少一些,因为我们必须将原始类型的大小从intlong增大一倍,然后再扩大到更大的格式。

更多!

通过注意我们只需要计算sqrt(n)即可初始化n个值的筛子,从而可以大大增加筛子的有效尺寸。 我们可以反过来说,可以使用完全填充的n个值的筛子填充另一个n 2个值的筛子。 在这种情况下,我们只想填充一个波段,而不是整个n 2筛。 现在,我们的内存中筛子可以覆盖最多约40位数字的数字(以10为基数),基于磁盘的筛子可以跳到多达60位数字的数字(以10为基数),减去较大值所需的空间。

没有理由不能进一步采用这种方法–使用小筛子来引导较大的瞬态筛子,然后依次使用它来填充更大的筛子。

但是这需要多长时间?

是的,有摩擦。 初始化n个值的筛网的成本为O(n 2 。 您可以使用各种调整来减少常数,但是到了一天结束时,您将访问每个节点一次( O(n) ),然后在每个这些点之外访问一些与n成正比的滚动值。 值得一提的是,保留CPU的缓存体系结构可能会产生很大的不同。

实际上,任何最新的系统都应能够在几秒钟内创建一个包含前百万个素数的筛子。 将筛子激增到最初的十亿个素数,如果JVM堆空间有限迫使我们大量使用磁盘,时间可能跳到一周,甚至一个月。 我的直觉是,填充TB磁盘需要花费数月甚至数年的服务器场时间

何必呢 ?

对于我们大多数人来说,主要收获是如何用小种子(例如n = 1000的筛子)开始收集并根据需要透明地进行生长的演示。 对于素数,这很容易,但是想像一下RSS提要使用相同的方法并不是一件容易的事。 我们习惯于将Iterators视为Collections的一些乏味方面,但实际上,将它们用作Iterable的一部分时,它们为我们提供了很多灵活性。

大型筛分也是一个实际原因-分解大量。 有几种很好的算法可以分解大量数据,但是它们很昂贵-即使在服务器场中,即使是“少量”数据也可能需要数月或数年。 这就是为什么第一步始终要使用“小”素数进行试验划分的原因-这可能需要一天的时间。

源代码

好消息是我已经为此发布了源代码……坏消息是当我处理Project Euler问题时,这是正在进行的涂鸦的一部分。 (这里没有解决方案–完全是对问题启发的思想探索。因此,代码有些粗略,不应用于决定是否邀请我参加面试(除非给您留下深刻的印象): http ://github.com/beargiles/projecteuler。

翻译自: https://www.javacodegeeks.com/2014/07/getting-an-infinite-list-of-primes-in-java.html

自然数 素数 质数

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

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

相关文章

mysql 大数据 join_MySQL JOIN算法原理

MySQL的JOIN相关操作&#xff0c;是通过“嵌套循环连接算法&#xff0c;NLJ”或者该算法的优化变体“块嵌套循环连接算法&#xff0c;BNLJ”来实现的。##### 嵌套循环连接算法两个表join时&#xff0c;可以简单理解为两层for循环&#xff0c;外层循环一般称作驱动表&#xff0c…

windows安装python3步骤_Windows下python3和python2安装与一起使用

一、python2和python3安装 2、安装步骤&#xff0c;直接双击运行&#xff0c;记得勾选添加环境变量就可以。图片1.png 3、安装已经选择了添加这个环境变量&#xff0c;所以不用再去配置。 如果没有勾选&#xff0c;得自己去设置。 鼠标右键我的电脑 -> 属性 -> 点击高级系…

mysql ondelete_MySQL on delete cascade语句

在本教程中&#xff0c;您将学习如何使用MySQL ON DELETE CASCADE引用操作来执行外键从多个相关表中删除数据。在上一个教程中&#xff0c;我们学习了如何使用单个DELETE语句从一个或多个相关表中删除数据。但是&#xff0c;MySQL提供了一种更为有效的方法&#xff0c;称为ON D…

您想了解的所有Throwable

本文是有关异常的教程。 但不是通常的一种。 其中有许多内容可以告诉您异常的含义&#xff0c;如何抛出异常&#xff0c;捕获异常&#xff0c;已检查异常与运行时异常之间的区别&#xff0c;等等。 没有必要了。 这对您来说也很无聊。 如果没有&#xff0c;那么请阅读其中的一本…

python构建二叉树_BinaryTree:学习二叉树的Python库

Python部落(python.freelycode.com)组织翻译&#xff0c;禁止转载&#xff0c;欢迎转发。简介&#xff1a; 您是否在为考试、作业或技术面试学习二叉树&#xff1f; Binarytree是一个Python库&#xff0c;它通过一个简单的API生成二叉树&#xff0c;可以进行检查和操作。它让您…

mysql union as 注入_sql注入入门 之 mysql 常规注入 [ union方式 ]

1,常规数字型 mysql 实例注入点,如下:1https://www.vuln.com/md_materia_profile_view.php?viewid22,依旧先尝试下经典的单引号,如下,虽然没暴露出明显的数据库报错信息,但我们发现,此时返回的页面已经异常了,经验判断,十有八九是个注入点,先不管那么多,我们继续1https://www.…

gradle docker_带有Gradle的Docker容器分为4个步骤

gradle docker您是否需要通过Java Web应用程序创建Docker映像&#xff1f; 您在使用Gradle吗&#xff1f; 如果是这样&#xff0c;那么您距Docker nivana仅4步之遥。 对于此示例&#xff0c;我将使用一个简单的Spring Boot应用程序。 您可以在我的名为galoshe的Github存储库中…

mysql数据库连接关闭_解决mysql数据库连接自动关闭问题

MySQL是一个小型关系型数据库管理系统&#xff0c;由于MySQL体积小、速度快、总体拥有成本低&#xff0c;尤其是开放源码这一特点&#xff0c;许多中小型网站为了降低网站总体拥有成本而选择了MySQL作为网站数据库。关于mysql自动关闭服务的现象&#xff0c;可以通过mysql服务器…

python socket编程_Python学习记录-socket编程

1. OSI七层模型详解2. Python socket 什么是 Socket? Socket又称”套接字”&#xff0c;应用程序通常通过”套接字”向网络发出请求或者应答网络请求&#xff0c;使主机间或者一台计算机上的进程间可以通讯。 Python 提供了两个级别访问的网络服务&#xff1a; 低级别的网络服…

REST / HTTP方法:POST与PUT与PATCH

每个HTTP请求都包含一个方法 &#xff08;有时称为verb &#xff09;&#xff0c;该方法指示对标识的资源执行的操作。 在构建RESTful Web服务时&#xff0c;HTTP方法POST通常用于创建资源&#xff0c;而PUT用于资源更新。 尽管在大多数情况下这很好&#xff0c;但使用PUT进行…

判断frame是否已创建_类的创建

1. 士兵 许三多 有一把 AK47 2. 士兵 可以开火 3. 枪 能够 发射 子弹 4. 枪 装填 子弹---增加子弹数量 class Gun:def __init__(self,type):self.type type# 刚开始枪没有子弹self.bullet_count 0def __str__(self):return ("%s 已到位" % self.type)def shoot(sel…

mysql 安装盒子_Windows2008 装 MySQL 问题

昨天在2008里装MySQL&#xff0c;遇以了一些问题&#xff0c;装的是mysql-5.6.20-winx64.msi版本&#xff0c;不知道是版本太新还是兼容&#xff0c;还是系统权限配置问题&#xff0c;老是报错&#xff0c;多数是杂乱的错误&#xff0c;这里主要记一下MySQL的错误&#xff1a;安…

@select注解_Mybatis基本知识十七:Mybatis注解式开发-单表注解式开发

上一篇文章&#xff1a;《Mybatis基本知识十六&#xff1a;查询缓存之第三方查询缓存》若文中有纰漏,请多多指正&#xff01;&#xff01;&#xff01;1.前言使用Mybatis进行开发&#xff0c;不仅可以使用mapper配置文件进行开发&#xff0c;也可以使用注解的方式。映射文件中无…

mysql主从切换机制torch_MySQL Replication设置(Master/Slave)实现主从复制

一、Master配置1、my.cnf配置# vim /etc/mysql/mariadb.conf.d/50-server.cnf[mysqld]log-binmysql-bin //[必须]启用二进制日志server-id140 //[必须]服务器唯一ID&#xff0c;默认是1&#xff0c;一般取IP最后一段2、重启mysqlsudo service mysql restart3、在主服务器上建立…

junit测试线程_一个在自己的线程中运行测试的JUnit规则

junit测试线程有时&#xff0c;能够在单独的线程中运行JUnit测试会很有帮助。 特别是在编写与封装的ThreadLocal或类似对象进行交互的集成测试时&#xff0c;这可能会派上用场。 单独的线程将隐式确保每次测试运行都未初始化threadlocal的与线程相关的引用。 这篇文章介绍了提供…

maven servlet配置_第一个Servlet配置

使用IntelliJ IDEA创建一个Simple Maven项目2. Add Framework Support3. 配置Tomcat打开菜单Run -> 选择Edit Configuration 如果侧边栏没有Tomcat&#xff0c;点击“”号 -> 选择“Tomcat Server” -> 选择“Local”&#xff0c;到此画面 ,Apply -> OK4. 在Tomcat…

如何将四元数方向转化为旋转举证_是否有将四元数旋转转换为欧拉角旋转的算法?...

frodo2975..7我一直在寻找类似解决方案的几天,我终于遇到了这个网站,它有一个将四元数转换为任意Euler和Tait-Bryan旋转的算法!这是代码:///// Quaternion to Euler///enum RotSeq{zyx, zyz, zxy, zxz, yxz, yxy, yzx, yzy, xyz, xyx, xzy,xzx};void twoaxisrot(double r11, do…

使用Spring Boot和DJL进行深度学习

总览 这是Spring Boot上的另一篇文章 &#xff0c;该文章将展示如何使用Deep Java Library &#xff08;DJL&#xff09;构建示例Web应用程序&#xff0c; Deep Java Library &#xff08;DJL&#xff09;是Java的开源深度学习库&#xff0c;用于诊断X射线图像上的COVID-19。 …

ad域管理与维护_U-Mail邮件系统LDAP/AD同步极大提升办公效率

每一位办公族&#xff0c;可能都遇到过这样的问题&#xff1a;1、随着信息化高速发展和企业“互联网”的深入&#xff0c;越来越多的办公平台和软件被开发出来&#xff0c;正如移动互联网端APP应用层出不穷一样&#xff0c;给人们带来了极大地便利性。2、凡事有利有弊&#xff…

r java_如何在R中使用JAVA写的程序包?

不过我对 Java 真的不太熟悉&#xff0c;按照教程调用这个 LLDA 包之后只会使用 inferencer。如果你不嫌麻烦可以考虑先用 Java 计算出结果&#xff0c;然后在 R 中载入这些结果.具体步骤如下&#xff1a;0 - 文件夹 JGibbLDA-v.1.0 放在 R 的工作目录下。1 - 用 JDK 和他提供的…