Haskell 中的素筛

2023-12-29

我对 Haskell 很陌生,我只是想找到前 200 万个素数的总和。我正在尝试使用筛子生成素数(我认为埃拉托色尼筛子?),但它真的很慢,我不知道为什么。这是我的代码。

sieve (x:xs) = x:(sieve $ filter (\a -> a `mod` x /= 0) xs)
ans = sum $ takeWhile (<2000000) (sieve [2..])

提前致谢。


它非常慢,因为该算法是一种试除法,不会停止于平方根。

如果你仔细观察算法的作用,你会发现对于每个素数p,其不具有较小素因数的倍数将从候选列表中删除(具有较小素因数的倍数之前已被删除)。

因此,每个数字都除以所有素数,直到它作为其最小素因数的倍数被删除,或者如果它是素数,则它出现在剩余候选列表的开头。

对于合数来说,这并不是特别糟糕,因为大多数合数都有小的素因数,并且在最坏的情况下,最小的素因数n不超过√n.

But the primes are divided by all smaller primes, so until the kth prime is found to be prime, it has been divided by all k-1 smaller primes. If there are m primes below the limit n, the work needed to find all of them prime is

(1-1) + (2-1) + (3-1) + ... + (m-1) = m*(m-1)/2

部门。由素数定理 http://en.wikipedia.org/wiki/Prime_number_theorem,下面的素数个数n是渐进的n / log n (where log表示自然对数)。消除复合材料的工作可以粗略地限制为n * √n划分,所以不能太小n与花在素数上的工作相比,这是可以忽略不计的。

For the primes to two million, the Turner sieve needs roughly 1010 divisions. Additionally, it needs to deconstruct and reconstruct a lot of list cells.

试除法止于平方根,

isPrime n = go 2
  where
    go d
      | d*d > n        = True
      | n `rem` d == 0 = False
      | otherwise      = go (d+1)

primes = filter isPrime [2 .. ]

would need fewer than 1.9*109 divisions (brutal estimate if every isPrime n check went to √n - actually, it takes only 179492732 because composites are generally cheap)(1) and much fewer list operations. Additionally, this trial division is easily improvable by skipping even numbers (except 2) as candidate divisors, which halves the number of required divisions.

埃拉托色尼筛不需要任何划分,只使用O(n * log (log n))操作,速度要快得多:

primeSum.hs:

module Main (main) where

import System.Environment (getArgs)
import Math.NumberTheory.Primes

main :: IO ()
main = do
    args <- getArgs
    let lim = case args of
                (a:_) -> read a
                _     -> 1000000
    print . sum $ takeWhile (<= lim) primes

并以 1000 万的限制运行它:

$ ghc -O2 primeSum && time ./primeSum 10000000
[1 of 1] Compiling Main             ( primeSum.hs, primeSum.o )
Linking primeSum ...
3203324994356

real    0m0.085s
user    0m0.084s
sys     0m0.000s

我们让试除法只运行到 100 万(将类型固定为Int):

$ ghc -O2 tdprimeSum && time ./tdprimeSum 1000000
[1 of 1] Compiling Main             ( tdprimeSum.hs, tdprimeSum.o )
Linking tdprimeSum ...
37550402023

real    0m0.768s
user    0m0.765s
sys     0m0.002s

而特纳筛只能到100000:

$ ghc -O2 tuprimeSum && time ./tuprimeSum 100000
[1 of 1] Compiling Main             ( tuprimeSum.hs, tuprimeSum.o )
Linking tuprimeSum ...
454396537

real    0m2.712s
user    0m2.703s
sys     0m0.005s

(1) The brutal estimate is

2000000
   ∑ √k ≈ 4/3*√2*10^9
 k = 1

评估为两位有效数字。由于大多数数字都是由一个小质因数组成的复合数 - 一半的数字是偶数并且只进行一次除法 - 这大大高估了所需的除法数量。

仅考虑素数即可获得所需除法数量的下限:

   ∑ √p ≈ 2/3*N^1.5/log N
 p < N
p prime

which, for N = 2000000 gives roughly 1.3*108. That is the right order of magnitude, but underestimates by a nontrivial factor (decreasing slowly to 1 for growing N, and never greater than 2 for N > 10).

除了素数之外,素数的平方和两个相近素数的乘积也需要试除达到(接近)√k因此,如果数量足够多的话,将对整体工作做出重大贡献。

然而,处理半素数所需的除法次数受到常数倍数的限制

N^1.5/(log N)^2

所以对于非常大的N相对于处理素数的成本来说,它可以忽略不计。但在试分割完全可行的范围内,它们仍然做出了重大贡献。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Haskell 中的素筛 的相关文章

  • 应用程序中 GC 长时间暂停

    我当前运行的应用程序需要最大堆大小为 16GB 目前我使用以下标志来处理垃圾收集 XX UseParNewGC XX UseConcMarkSweepGC XX CMSInitiatingOccupancyFraction 50 XX Di
  • 为什么某些 float < integer 比较比其他比较慢四倍?

    将浮点数与整数进行比较时 某些值对的计算时间比类似大小的其他值要长得多 例如 gt gt gt import timeit gt gt gt timeit timeit 562949953420000 7 lt 56294995342100
  • 如何从具有函数依赖关系的类型类中获取和使用依赖类型?

    如何从具有函数依赖关系的类型类中获取和使用依赖类型 为了澄清并给出我最近的尝试的一个例子 从我正在编写的实际代码中最小化 class Identifiable a b a gt b where if you know a you know
  • 在列表中查找元素及其索引

    我需要让列表的两个元素都满足谓词and这些元素的索引 我可以通过以下方式实现这一点 import Data List findIndices list Int list 3 2 4 1 9 indices findIndices gt 2
  • 为什么我不能声明推断类型?

    我有以下内容 runcount Eq a Num b gt a gt b runcount runcountacc 0 runcountacc Eq a Num b gt b gt a gt b runcountacc n runcount
  • 方法与管道

    在 Angular 应用程序中的模板插值中使用管道和方法有区别吗 例如 h1 name toLowerCase h1 vs h1 name lowercase h1 就性能而言 是有真正的收获还是只是个人喜好 我知道调用模板中的方法通常会降
  • OpenGL:顶点越多,性能越慢

    我正在开发一个程序的一部分 其中给定 xyz 坐标集合 制作 3D 模型 我已经完成了这张图片所需的所有功能 即平移 旋转 缩放 但是给出的 xyz 坐标越多 程序运行速度就越慢 我的程序在处理 29 000 个坐标时运行得非常流畅 但当我
  • n的渐近增长选择下限(n/2)

    如何找到 n select Floor n 2 的渐近增长 我试过 使用扩展并得到它等于 n n 1 floor n 2 1 n floor n 2 知道我该如何从那里去吗 感谢任何帮助 更喜欢提示而不是答案 我同意上面的答案 但想提供更多
  • 这是 unsafeCoerce 的安全使用吗?

    我遇到的情况是 我目前正在使用极其可怕的函数 unsafeCoerce 幸运的是 这并不是为了任何重要的事情 但我想知道这是否是该函数的安全使用 或者是否有其他方法可以解决其他人知道的这个特定问题 我的代码类似于以下内容 data Toke
  • Haskell数据类型转换问题

    我目前正在学习 Haskell 并且一直在编写一些非常简单的程序来练习 我的程序之一是 import System IO main do putStrLn Give me year y lt getLine let res show cal
  • Prolog中计算数字是否为素数

    我正在尝试计算输入是否是素数 但出了问题 这是我的代码 primeNumber X prime prime A 1 prime prime A B R is A mod B R 1 R A prime prime X B B lt A Ne
  • 添加到 SortedSet 及其复杂性

    MSDN 声明如下SortedSet T Add 方法 http msdn microsoft com en us library dd411709 28VS 100 29 aspx 如果 Count 小于内部数组的容量 则此方法的操作时间
  • 如何加速我的 Perl 程序?

    这确实是两个问题 但它们非常相似 为了简单起见 我想我应该把它们放在一起 Firstly 给定一个已建立的 Perl 项目 除了简单的代码优化之外 还有哪些不错的方法可以加速它 Secondly 用Perl从头开始编写程序时 有哪些好的方法
  • 如何加快 Java VM (JVM) 的启动时间?

    我正在运行启动多个 JVM 进程的测试 与 JVM 内运行的实际测试时间相比 JVM 的总结启动时间非常重要 我怎样才能加快速度 我已经使用了 client 选项 这确实有帮助 但没有我想要的那么多 还有其他方法吗 比如预加载一堆 JVM
  • 频繁插入已排序的集合

    我已经对集合 列表 进行了排序 并且我需要始终保持其排序 我目前在我的集合上使用 List BinarySearch 然后在正确的位置插入元素 我也尝试过在每次插入后对列表进行排序 但性能不可接受 有没有一种解决方案可以提供更好的性能 也许
  • Haskell/Idris 中的开放类型级别证明

    在 Idris Haskell 中 可以通过注释类型并使用 GADT 构造函数 例如使用 Vect 来证明数据的属性 但这需要将属性硬编码到类型中 例如 Vect 必须是与 List 不同的类型 是否有可能拥有具有开放属性集的类型 例如同时
  • C++ OpenCV imdecode 慢

    我将图像的字节数组从 C 发送到 C 库 我使用 OpenCV 版本 3 3 1 解码图像 BMP 图像解码速度很快 但 JPEG 图像解码速度很慢 如何加快 JPEG 图像的解码时间 多线程 GPU 解码性能 Resolution For
  • 用 OpenCL C 编写快速线性系统求解器

    我正在编写一个 OpenCL 内核 它将涉及求解线性系统 目前我的内核太慢了 提高线性系统部分的性能似乎是一个不错的起点 我还应该注意 我并没有尝试使我的线性求解器并行 我正在研究的问题在宏观层面上已经是令人尴尬的并行 以下是我编写的 C
  • 如何调试性能问题/优化您的流星应用程序

    我刚刚将 Meteor 应用程序部署到 Digital Ocean 上的生产服务器上 我注意到 对于大约 7500 个文档 完全获取对象 有选择地仅获取 3 个字段 并填充自动完成数据大约需要 3 5 秒 我相信对于如此数量的数据来说 它应
  • Java中精确的时间测量

    Java 提供了两种获取当前时间的方法 System nanoTime and System currentTimeMillis 第一个给出的结果以纳秒为单位 但实际精度比这要差得多 许多微秒 JVM 是否已经为每台特定机器提供了最佳的价值

随机推荐

  • C++ 命名空间内的 extern "C" 链接?

    namespace someNameSpace extern C void doSomething someOperations 我想跑doSomething 在 C 和 C 环境中 Is someNameSpace仍在封装doSometh
  • 如何自动将文件夹上传到azure?

    现在我有了这部分代码 它显示了目录中的所有文件夹 var dirPath path join C ILJATEST fs readdir dirPath function err files if err return console lo
  • 如何获取字符串最后一次出现的位置?

    我有一个函数可以提取 string 内 start 和 end 之间的内容 function get string between string start end string string ini strpos string start
  • 将指针传递给函数并修改它

    stackoverflow 和 C C 的新手 我正在努力实现二叉树并有一个简单的问题 可以说我有以下内容 struct Node int data Node right child Node left child void addNode
  • Java 8 函数接口对象的 Java Hashcode 和 Equals

    我有一些代码如下所示 import java util ArrayList import java util List import java util function Function class MyObj private final
  • 如何将 sp_executesql 结果放入变量中?

    我需要执行一段动态 SQL 然后需要将结果存储到变量中 我知道我可以使用sp executesql但找不到有关如何执行此操作的明确示例 如果你有 OUTPUT 参数 你可以这样做 DECLARE retval int DECLARE sSQ
  • Reveal.js HTML 代码语法高亮显示而不渲染

    针对 Reveal js 用户的问题 我试图在 Reveal js 演示文稿中显示 HTML 标记 问题是它在我的代码语法突出显示块中呈现 html 块 因此看不到标记 有没有解决的办法 下面的例子 section h2 Pretty Co
  • 将 import() 转换为同步

    我正在尝试转换我的所有节点require 进入import 然而 这些语句是异步的 我遇到了一些麻烦 现在我有 import as fs from fs const paths fs readdirSync src modules map
  • 将 Column(str) 转换为 (Float) ,ValueError: 无法将字符串转换为 float: 'Null'

    对不起 各位 我知道这个问题之前已经被回答过 我尝试了所有答案 也进行了研究 并尝试了不同的事情 4 个小时 我无法完成 我相信我的数据有一些奇怪的东西 所以按照我的数据和我的尝试 x pd DataFrame Cost 83 534625
  • 在膨胀布局中使用 setText() 到 TextView() 后,文本不显示

    是的 我知道以前有人问过类似的问题 但我尝试了很多 所以我在膨胀布局中的 TextView 中设置文本时遇到问题 我尝试了 setContentView 然后它可以工作 但是带有菜单的 Activity main xml 无法工作 所以我尝
  • Google AdSense 的 400 错误请求

    我正在运行一个使用 AJAX 请求和 History pushState 进行导航的网站 请求的内容代码包含Google的异步AdSense代码
  • ^= 32 将小写字母转换为大写字母,反之亦然,背后的想法是什么?

    我正在解决 codeforces 上的一些问题 通常我首先检查字符是大写还是小写英文字母 然后减去或添加32将其转换为相应的字母 但我发现有人这么做 32做同样的事情 这里是 char foo a foo 32 char bar A bar
  • 什么是可组合运行时类?

    我正在尝试使用 C WinRT 创建一个简单的 xaml 应用程序 我有 WPF 背景 拥有一个基类是很常见的 实现 INotifyPropertyChanged 并让其他类继承它 当我尝试对 C WinRT 执行相同操作时 我失败并出现错
  • 面向列的数据库与面向行的数据库

    我已经使用了很长时间的面向行的数据库设计 除了数据仓库项目和大数据示例之外 我还没有在 OLTP 应用程序中使用面向列的数据库设计 我的面向行的表看起来像 ID Make Model Month Miles Cost 1 BMW Z3 12
  • 如何跳出多个循环?

    给出以下代码 不起作用 while True Snip print out current state while True ok get input Is this ok y n if ok lower y break 2 This do
  • 从 Visual Studio 2019 将 ASP.NET Core 3.1 站点发布到 Azure 时出错

    我有一个预先存在的ASP NET 核心 3 0应用程序已成功部署到Azure 应用服务 使用AspNetCoreModuleV2模块 将应用程序升级到 今天发布的 后ASP NET 核心 3 1 应用程序在我的本地版本上正确构建并运行IIS
  • 从配置中读取 Azure 函数设置

    我使用带有属性的 Azure Functions 来定义功能 public static class PostPublishTimerTrigger FunctionName PostPublishTimerTrigger public s
  • 类型错误:createSlice 不是 vitest 中的函数

    我正在构建一个 tic tac toe 游戏 与 redux 进行反应 并尝试使用 vitest 进行测试 我已经设置了板片和商店 但是当尝试运行我的第一个测试时 我收到以下错误 Failed Suites 1 FAIL src slice
  • 将 NSArray 复制到空 NSArray 中

    我有第一个 NSArrayfirstArray我做 firstArray removeAllObjects 当我想用另一个数组的内容填充它之后secondArray 这样写对吗 firstArray secondArray No first
  • Haskell 中的素筛

    我对 Haskell 很陌生 我只是想找到前 200 万个素数的总和 我正在尝试使用筛子生成素数 我认为埃拉托色尼筛子 但它真的很慢 我不知道为什么 这是我的代码 sieve x xs x sieve filter a gt a mod x