如何使用 6*k +- 1 规则生成素数

2024-01-14

我们知道 3 以上的所有素数都可以使用以下方法生成:

6 * k + 1
6 * k - 1

然而,从上述公式生成的所有数字都不是素数。

For Example:    
6 * 6 - 1 = 35 which is clearly divisible by 5.

为了消除这种情况,我使用了筛分法并删除了作为上述公式生成的数字的因子的数字。

使用事实:

如果一个数没有质因数,则称该数为质数。

  1. 因为我们可以使用上面的公式生成所有素数。
  2. 如果我们可以删除上述数字的所有倍数,我们就只剩下质数。

生成 1000 以下的素数。

ArrayList<Integer> primes = new ArrayList<>();
primes.add(2);//explicitly add
primes.add(3);//2 and 3
int n = 1000;
for (int i = 1; i <= (n / 6) ; i++) {
//get all the numbers which can be generated by the formula
    int prod6k = 6 * i;
    primes.add(prod6k - 1);
    primes.add(prod6k + 1);
}
for (int i = 0; i < primes.size(); i++) {
    int k = primes.get(i);
    //remove all the factors of the numbers generated by the formula
    for(int j = k * k; j <= n; j += k)//changed to k * k from 2 * k, Thanks to DTing
    {           
        int index = primes.indexOf(j); 
        if(index != -1)
            primes.remove(index);
    }
}
System.out.println(primes);

然而,这种方法确实能正确生成素数。这运行得更快,因为我们不需要检查我们在筛子中检查的所有数字。

我的问题是我是否遗漏了任何边缘情况?这会好很多,但我从未见过有人使用它。难道我做错了什么?

这种方法可以进一步优化吗?


采取boolean[]而不是ArrayList速度要快得多。

int n = 100000000;
boolean[] primes = new boolean[n + 1];
for (int i = 0; i <= n; i++)
    primes[i] = false;
primes[2] = primes[3] = true;
for (int i = 1; i <= n / 6; i++) {
    int prod6k = 6 * i;
    primes[prod6k + 1] = true;
    primes[prod6k - 1] = true;
}
for (int i = 0; i <= n; i++) {
    if (primes[i]) {
        int k = i;
        for (int j = k * k; j <= n && j > 0; j += k) {
               primes[j] = false;
        }
      }
}
for (int i = 0; i <= n; i++)
    if (primes[i]) 
        System.out.print(i + " ");

5 是根据您的条件生成的第一个数字。我们来看一下 25 以内生成的数字:

5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25

现在,当我们使用埃拉托色尼筛算法时,让我们看看这些相同的数字:

5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25

删除2后:

5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25

删除3后:

5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25

这和第一套是一样的!请注意,它们都包含 25,这不是质数。如果我们仔细想想,这是一个显而易见的结果。考虑任意 6 个连续数字的组:

6k - 3、6k - 2、6k - 1、6k、6k + 1、6k + 2

如果我们稍微考虑一下,我们会得到:

3*(2k - 1)、2*(3k - 1)、6k - 1、6*(k)、6k + 1、2*(3k + 1)

任意一组 6 个连续数字中,其中 3 个可被 2 整除,其中 2 个可被 3 整除。这些正是我们迄今为止删除的数字!所以:

你的算法只能使用6k - 1 and 6k + 1与埃拉托斯特尼筛法的前两轮完全相同。

与筛子相比,这也是一个相当不错的速度改进,因为我们不必添加所有这些额外的元素来删除它们。这解释了为什么你的算法有效以及为什么它不会错过任何案例;因为它和筛子完全一样。


无论如何,我同意一旦你生成了素数,你的boolean way is 迄今为止最快的。我已经使用你的设置了一个基准ArrayList方式,你的boolean[]方式,以及我自己的使用方式LinkedList and iterator.remove()(因为删除速度很快LinkedList。这是我的测试工具的代码。请注意,我运行了 12 次测试以确保 JVM 已预热,并且打印了列表的大小并更改了n试图阻止太多分支预测 https://stackoverflow.com/q/11227809/1768232优化。您还可以使用以下方法在所有三种方法中获得更快的速度+= 6在初始种子中,而不是prod6k:

import java.util.*;

public class PrimeGenerator {
  public static List<Integer> generatePrimesArrayList(int n) {
    List<Integer> primes = new ArrayList<>(getApproximateSize(n));
    primes.add(2);// explicitly add
    primes.add(3);// 2 and 3

    for (int i = 6; i <= n; i+=6) {
      // get all the numbers which can be generated by the formula
      primes.add(i - 1);
      primes.add(i + 1);
    }

    for (int i = 0; i < primes.size(); i++) {
      int k = primes.get(i);
      // remove all the factors of the numbers generated by the formula
      for (int j = k * k; j <= n; j += k)// changed to k * k from 2 * k, Thanks
                                         // to DTing
      {
        int index = primes.indexOf(j);
        if (index != -1)
          primes.remove(index);
      }
    }
    return primes;
  }

  public static List<Integer> generatePrimesBoolean(int n) {
    boolean[] primes = new boolean[n + 5];
    for (int i = 0; i <= n; i++)
      primes[i] = false;
    primes[2] = primes[3] = true;

    for (int i = 6; i <= n; i+=6) {
      primes[i + 1] = true;
      primes[i - 1] = true;
    }

    for (int i = 0; i <= n; i++) {
      if (primes[i]) {
        int k = i;
        for (int j = k * k; j <= n && j > 0; j += k) {
          primes[j] = false;
        }
      }
    }

    int approximateSize = getApproximateSize(n);
    List<Integer> primesList = new ArrayList<>(approximateSize);
    for (int i = 0; i <= n; i++)
      if (primes[i])
        primesList.add(i);

    return primesList;
  }

  private static int getApproximateSize(int n) {
    // Prime Number Theorem. Round up
    int approximateSize = (int) Math.ceil(((double) n) / (Math.log(n)));
    return approximateSize;
  }

  public static List<Integer> generatePrimesLinkedList(int n) {
    List<Integer> primes = new LinkedList<>();
    primes.add(2);// explicitly add
    primes.add(3);// 2 and 3

    for (int i = 6; i <= n; i+=6) {
      // get all the numbers which can be generated by the formula
      primes.add(i - 1);
      primes.add(i + 1);
    }

    for (int i = 0; i < primes.size(); i++) {
      int k = primes.get(i);
      for (Iterator<Integer> iterator = primes.iterator(); iterator.hasNext();) {
        int primeCandidate = iterator.next();
        if (primeCandidate == k)
          continue; // Always skip yourself
        if (primeCandidate == (primeCandidate / k) * k)
          iterator.remove();
      }
    }
    return primes;
  }

  public static void main(String... args) {
    int initial = 4000;

    for (int i = 0; i < 12; i++) {
      int n = initial * i;
      long start = System.currentTimeMillis();
      List<Integer> result = generatePrimesArrayList(n);
      long seconds = System.currentTimeMillis() - start;
      System.out.println(result.size() + "\tArrayList Seconds: " + seconds);

      start = System.currentTimeMillis();
      result = generatePrimesBoolean(n);
      seconds = System.currentTimeMillis() - start;
      System.out.println(result.size() + "\tBoolean Seconds: " + seconds);

      start = System.currentTimeMillis();
      result = generatePrimesLinkedList(n);
      seconds = System.currentTimeMillis() - start;
      System.out.println(result.size() + "\tLinkedList Seconds: " + seconds);
    }
  }
}

以及最近几次试验的结果:

3432    ArrayList Seconds: 430
3432    Boolean Seconds: 0
3432    LinkedList Seconds: 90
3825    ArrayList Seconds: 538
3824    Boolean Seconds: 0
3824    LinkedList Seconds: 81
4203    ArrayList Seconds: 681
4203    Boolean Seconds: 0
4203    LinkedList Seconds: 100
4579    ArrayList Seconds: 840
4579    Boolean Seconds: 0
4579    LinkedList Seconds: 111
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 6*k +- 1 规则生成素数 的相关文章

  • Java将字符串解析为double

    如何解析字符串中的这个 Double 00034800 变成 Double 值 最后两位数字实际上是小数点 所以我正在寻找的结果是348 00 是否有这样的格式可以与十进制格式一起使用 Well String s 00034800 doub
  • 连接外部 Accumulo 实例和 java

    我正在尝试使用 Accumulo 连接到虚拟机 问题是 我无法将其连接到 Java 中 我可以看到 Apache 抛出的网页 但我无法让它与代码一起工作 我认为这是缺乏知识的问题而不是真正的问题 但我找不到这方面的文档 所有示例都使用 lo
  • 非易失性领域的出版与阅读

    public class Factory private Singleton instance public Singleton getInstance Singleton res instance if res null synchron
  • Java 中的 <-- 是什么? [复制]

    这个问题在这里已经有答案了 我遇到了下面的片段 它输出到4 3 2 1 我从来没有遇到过 lt 在爪哇 Is lt 使 var1 的值变为 var2 的运算符 public class Test public static void mai
  • java中如何知道一条sql语句是否执行了?

    我想知道这个删除语句是否真的删除了一些东西 下面的代码总是执行 else 是否删除了某些内容 执行此操作的正确方法是什么 public Deleter String pname String pword try PreparedStatem
  • Mockito 和 Hamcrest:如何验证 Collection 参数的调用?

    我遇到了 Mockito 和 Hamcrest 的泛型问题 请假设以下界面 public interface Service void perform Collection
  • 如何使用双重调度来分析图形基元的交集?

    我正在分析图形基元 矩形 直线 圆形等 的交互并计算重叠 相对方向 合并等 这被引用为双重调度的一个主要示例 例如维基百科 http en wikipedia org wiki Double dispatch 自适应碰撞算法通常要求 不同的
  • 在java程序中使用c++ Dll

    我正在尝试使用System LoadLibrary 使用我用 C 编写的一个简单的 dll UseDllInJava java import com sun jna Library import com sun jna Native imp
  • UseCompressedOops JVM 标志有什么作用以及何时应该使用它?

    HotSpot JVM 标志是什么 XX UseCompressedOops我应该做什么以及什么时候使用它 在 64 位 Java 实例上使用它 与不使用它 时 我会看到什么样的性能和内存使用差异 去年大多数 HotSpot JVM 都默认
  • 使用 Proguard 通过 Dropbox.com 库混淆 Android 应用程序

    我刚刚创建了一个需要 Dropbox com API 库的 Android 应用程序 我现在尝试在 发布 模式下构建应用程序 并希望在代码上运行混淆器以对其进行混淆 但是 每当我尝试运行 Proguard 时 都会收到以下错误 Progua
  • Android - 存储对ApplicationContext的引用

    我有一个静态 Preferences 类 其中包含一些应用程序首选项和类似的内容 可以在那里存储对 ApplicationContext 的引用吗 我需要该引用 以便我可以在不继承 Activity 的类中获取缓存文件夹和类似内容 你使用的
  • Java 8 Stream,获取头部和尾部

    Java 8 引入了Stream http download java net jdk8 docs api java util stream Stream html类似于 Scala 的类Stream http www scala lang
  • 从三点求圆心的算法是什么?

    我在圆的圆周上有三个点 pt A A x A y pt B B x B y pt C C x C y 如何计算圆心 在Processing Java 中实现它 我找到了答案并实施了一个可行的解决方案 pt circleCenter pt A
  • java实现excel价格、收益率函数[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 我所有的 java 应用程序现在都会抛出 java.awt.headlessException

    所以几天前我有几个工作Java应用程序使用Swing图书馆 JFrame尤其 他们都工作得很好 现在他们都抛出了这个异常 java awt headlessexception 我不知道是什么改变了也许我的Java版本不小心更新了 谢谢你尽你
  • 适用于多应用项目的 Grunt 和 requirejs 优化器

    我在让 Grunt 对具有以下结构的项目执行 requirejs 优化时遇到问题 static js apps app js dash js news js many more app files build collections lib
  • 使用 Apache 允许 Glassfish 和 PHP 在同一服务器中协同工作

    是否可以建立从 Java 到 php 文件的桥梁 我有一个用 Java 编写的应用程序 我需要执行http piwik org http piwik org 这是用 PHP 编写的 在服务器中 我正在运行 PHP 但无法从浏览器访问 php
  • 带 getClassLoader 和不带 getClassLoader 的 getResourceAsStream 有什么区别?

    我想知道以下两者之间的区别 MyClass class getClassLoader getResourceAsStream path to my properties and MyClass class getResourceAsStre
  • Java 的“&&”与“&”运算符

    我使用的示例来自 Java Herbert Schildt 的完整参考文献 第 12 版 Java 是 14 他给出了以下 2 个示例 如果阻止 第一个是好的 第二个是错误的 因此发表评论 public class PatternMatch
  • Spring 作为 JNDI 提供者?

    我想使用 Spring 作为 JNDI 提供程序 这意味着我想在 Spring 上下文中配置一个 bean 可以通过 JNDI 访问该 bean 这看起来像这样

随机推荐

  • 迁移工作项数据时出错[重复]

    这个问题在这里已经有答案了 迁移工作项数据时出现以下错误 由于以下原因 配置失败 com opshub exceptions DataVaIidationException OpsHub 012017 字段 映射名称 10 1 I 31XD
  • HTML 重复 ID

    我的控件是根据用户输入动态构建的 有nID 也是动态的文本框 然而 我没有预见到这个 HTML 会在同一 html 页面的其他地方重用 我现在面临的问题是重复的 ID 这导致我的 jQuery 函数无法正常工作 我确实明白 ID 应该是唯一
  • Math.Net 解值为 0 的线性方程组

    我试图在 Math Net 中求解矩阵 当矩阵的实际解之一为 0 时 但我得到 NaN 作为结果 这是一个示例矩阵 为简单起见已对其进行了简化 1 0 1 10000 0 1 1 1000 0 0 0 0 代码示例 public void
  • 重构 Form_for 创建多态关联中注释的方法

    我正在研究我的第一个多态关联关系 但在重构我的 form for 创建评论时遇到了麻烦 我尝试浏览多态协会 RailsCastshttp railscasts com episodes 154 polymorphic association
  • .htaccess,将404错误重写到其他域

    如何将所有 404 错误重定向到另一个域 我找到了 Error 404 http example com error html 但是我需要 if Error 404 http example com 1 我试过了 RewriteEngine
  • python 中的随机()

    在Python中的函数random 均匀地生成半开范围 0 0 1 0 内的随机浮点数 原则上它能生成 0 0 即零 和 1 0 即统一 吗 实际应用中是什么样的场景呢 0 0可以生成 1 0不能 因为它不在范围内 因此 相对于 生成概率0
  • 在 Swift 中将图像(或视频)发布到服务器

    您好 我正在使用 NSURLSession 快速将 json 数据发布到服务器 如下所示 var request NSMutableURLRequest URL NSURL string http mypath com var sessio
  • 2016 年最佳密码存储算法

    实际上我读了很多与算法相关的帖子 比如md5 sha1等等 但我仍然不确定哪一种是当今最安全且最好使用的 我是网络开发的初学者 我要求世界上所有最好的程序员来教我并向我展示 我希望你们能给我选择和使用它的例子 谢谢 顺便 2016 年如何安
  • Django、apache、mod_wsgi - 错误:脚本标头过早结束

    Apache 以调试模式登录 Tue Dec 21 11 36 33 2010 info client 1 53 149 114 mod wsgi pid 24831 process mysite application mysite co
  • 按键对 React Native 部分列表进行排序和分组

    我有一个部分列表 其中填充了来自 firebase 的数据 该列表显示按日期划分的事件信息 当前月份显示为THIS MONTH和其他日期使用其速记值JAN FEB etc 我得到的数据很好并且可以很好地显示它 但我不知道如何按日期对数据数组
  • 使用具有多个条件的 If 语句

    我编写了以下代码 基本上应该相应地为一些框着色 每当我运行此代码时 它都会运行第一种情况 即即使需要选择其他情况也是如此 这是代码 Sub Macro quaterly If Sheet2 Range B6 Value 1 Or 2 Or
  • 如何选择每组的前N行

    我的三重存储中有一些数据 例如 Subject Predicate Object
  • ASP.NET HttpContext 缓存在插入后立即删除

    我有一个 ASP NET 4 Web 服务 它有一个ImportModule行动在一个ModuleController控制器 这就是它的工作原理 用户将模块上传为 CSV 文件 正在使用该文件读取HttpPostedFileBase Inp
  • PHP 致命错误:在非对象上调用成员函数bind_param() [重复]

    这个问题在这里已经有答案了 我有以下代码 statement mysqli gt prepare INSERT INTO paypal transactions txn id payer email mc gross mc currency
  • Go的interface{}和C中的void*一样吗?

    由于类型变量interface 可以有任何值 这是否意味着它本质上是一个像 C 中的 void 一样的通用指针 而C的void 指针和 Go 的interface 变量共享可以存储任意类型的属性 但有一个很大的区别 Go 接口变量还存储它们
  • 可以用jade/pug 编写PHP 吗?

    是否可以 如果是这样 怎么办 如果不是 如果我需要在文档中编写 PHP 我是否必须放弃 pug 环顾四周后 我没有找到任何人解决了这个问题 您可以将 PHP 嵌入到 Pug 模板中 就像您希望通过相对不受干扰的任何文字纯文本一样 有文档中涵
  • Xcode 11 升级 |找不到 iPhone X 模拟器 | XRPackageModel 9.0.omo

    自从升级后还有其他人得到这个Xcode 10 3 https developer apple com documentation xcode release notes xcode 10 3 release notes to Xcode 1
  • WPF 拖动滚动功能无法正常工作

    我想在我的应用程序中实现拖动滚动功能 但在路上遇到了问题 有谁能够帮助我 我有一个 ScrollViewer 里面有一个 ItemsControl 在 ItemsTemplate 中我有一个 UserControl 我想将该 UserCon
  • UserWarning:X 没有有效的特征名称,但 LogisticRegression 已安装了特征名称

    我在 Flask 中编写了一个程序来获取用户的输入 以输入长度和宽度来预测鱼的类型 但是当我输入时 它会显示一个错误 称为 UserWarning X does not have valid feature names but Logist
  • 如何使用 6*k +- 1 规则生成素数

    我们知道 3 以上的所有素数都可以使用以下方法生成 6 k 1 6 k 1 然而 从上述公式生成的所有数字都不是素数 For Example 6 6 1 35 which is clearly divisible by 5 为了消除这种情况