ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: aoe1981

无聊之中,做了一个质数判断,尚待完善

[复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-1-20 11:07 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖已被收录到知识树中,索引项:其他结构和算法
hnwxm 发表于 2014-1-20 10:27
用产生素数表的方法即可,当然可以再提速,一般讲没必要。

产生素数表的方法,这个提法好,概括性强,高手!!!

TA的精华主题

TA的得分主题

发表于 2014-1-20 12:43 | 显示全部楼层
楼住的几个问题:

1、素性判定
有很多快速的素性判定:
  Fermat Primality Test
  Solovay - Strassen Primality Test
  Miller - Rabin Primality Test
  Baillie - PSW Primality Test
  Elliptic Curve Primality Proving
  AKS Primality Test
最后两种是确定的判定一个数是否为素数,其余的都是高阶的可能性判定,即存在错误的可能。具体实现方式不妨在网上查一下。

2、素因数分解
通用且省事的办法,是根据自己需要,预先生成一定量的素数,如十万内或是百万内的,作为常数编译到程序里或是作为资源文件用的时候动态调用,更大的素数则是在此基础上通过筛选法计算而得。在需要对较大数作素因数分解的时候,完全动态的生成素数表是非常笨拙的方式,那是业余数学爱好者干的。

3、超大数的计算
超大数的计算是通过数组实现的,将一个数组理解为某个基数下的进制,每一个元素对应该进制下的某一位,比如十进制时第一个元素是个位数,第二个是十位数。通常基数选择为2的某次方或是10的某次方,前者适应计算机的内存和计算,后者对人而言更直观。
可以参考一下开放竞赛区里计算根号2那个帖子,基本的加减乘除四则运算在该贴里有正确的实现方法。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-1-20 14:36 | 显示全部楼层
aoe1981 发表于 2014-1-19 23:27
我测试到的一维数组最大上标是9637 0679,运行了24秒,得出素数个数556 4258,稠密度约5.77%。上标为9637 ...

你这个代码算法很明确,就是筛子法。

但是即使在VBA代码中,也还是有改进余地。

我研究了一下,做了test2、test3、test4一共3个阶段的改进,
现在test4可以达到Excel VBA算法的极限了。

我目前测试最大n=25*10^7 也可以计算,而且速度提高不少。

下面代码你去验证一下吧:
  1. Const n  As Long = 25 * 10 ^ 7 'k=13,679,317
  2. Sub SpeedCompare()
  3.     Dim i&, j&, n&, p&
  4.     p = 0
  5.    
  6.     Debug.Print " ": Debug.Print "-Begin-"
  7.     For j = 4 To 4
  8.         tms = Timer
  9.         For i = 1 To 10 ^ p
  10.             Run "Test" & j
  11.         Next
  12.         Debug.Print "Test" & j & ": " & Format(Timer - tms, "0.0000s")
  13.     Next
  14.     Debug.Print "--End--"
  15. End Sub
  16. Sub test1()
  17.     Dim i&, j&, k&, flag() As Boolean, arr&(), tms#
  18. '    tms = Timer
  19.     ReDim flag(n), arr(n)
  20.     For i = 2 To Sqr(n)
  21.         If Not flag(i) Then
  22.             For j = 2 * i To n Step i
  23.                 flag(j) = True
  24.             Next
  25.         End If
  26.     Next
  27.    
  28.     For i = 3 To n
  29.         If Not flag(i) Then arr(k) = i: k = k + 1
  30.     Next
  31.     ReDim Preserve arr(k - 1)
  32. '    MsgBox Format(Timer - tms, "0.000s ") & k
  33. '    If k < 65536 Then [a:a] = "": [a1].Resize(k) = Application.Transpose(arr)
  34. End Sub
  35. Sub test2()
  36.     Dim i&, j&, k&, flag() As Boolean, arr&(), tms#
  37. '    tms = Timer
  38.    
  39.     ReDim flag(n), arr(n \ 10)
  40.     For i = 2 To n Step 2
  41.         flag(i) = True
  42.     Next
  43.     For i = 3 To Sqr(n) Step 2
  44.         If Not flag(i) Then
  45.             For j = 3 * i To n Step i * 2
  46.                 flag(j) = True
  47.             Next
  48.         End If
  49.     Next
  50.    
  51.     For i = 3 To n
  52.         If Not flag(i) Then arr(k) = i: k = k + 1
  53.     Next
  54.     ReDim Preserve arr(k - 1)
  55. '    MsgBox Format(Timer - tms, "0.000s ") & k
  56. '    If k < 65536 Then [b:b] = "": [b1].Resize(k) = Application.Transpose(arr)
  57. End Sub
  58. Sub test3()
  59.     Dim i&, j&, k&, flag() As Boolean, arr&(), tms#
  60. '    tms = Timer
  61.    
  62.     ReDim flag(n \ 2), arr(n \ 10)
  63.     For i = 3 To Sqr(n) Step 2
  64.         If Not flag((i + 1) / 2) Then
  65.             For j = 3 * i To n Step i * 2
  66.                 flag((j + 1) / 2) = True
  67.             Next
  68.         End If
  69.     Next
  70.    
  71.     For i = 2 To n \ 2
  72.         If Not flag(i) Then arr(k) = i * 2 - 1: k = k + 1
  73.     Next
  74.     ReDim Preserve arr(k - 1)
  75. '    MsgBox Format(Timer - tms, "0.000s ") & k
  76. '    If k < 65536 Then [c:c] = "": [c1].Resize(k) = Application.Transpose(arr)
  77. End Sub
  78. Sub test4()
  79.     Dim i&, j&, k&, m&, t&, flag() As Boolean, arr&(), tms#
  80.     tms = Timer
  81.     m = n \ 2
  82.     ReDim flag(m)
  83. '    If n < 10 ^ 6 Then ReDim arr(m) Else ReDim arr(m \ 5)
  84.    
  85.     For i = 2 To Sqr(n) \ 2
  86.         If Not flag(i) Then
  87.             t = i * 2 - 1
  88.             For j = (i * 3 - 1) To m Step t
  89. '                t2 = j * 2 - 1
  90.                 flag(j) = True
  91.             Next
  92.         End If
  93.     Next
  94.    
  95.     For i = 2 To m - 2
  96.         If Not flag(i) Then k = k + 1 'arr(k) = i * 2 - 1: k = k + 1
  97.     Next
  98. '    ReDim Preserve arr(k - 1)
  99.     MsgBox Format(Timer - tms, "0.000s ") & Format(k, "#,##0")
  100. '    If k < 65536 Then [d:d] = "": [d1].Resize(k) = Application.Transpose(arr)
  101. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2020-7-19 05:52 | 显示全部楼层
aoe1981 发表于 2014-1-19 12:10
整理一下,以下代码可概括为:2+划2序列,大数据下估计此代码最优!

为了给大数据运算做准备,又做了优 ...

您老人家这样不断在窗体里改,没人愿意每次测试都去修改一次,写成Sub或Fun,更多人会参与进来的。

TA的精华主题

TA的得分主题

发表于 2020-7-20 15:27 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
香川群子 发表于 2014-1-20 14:36
你这个代码算法很明确,就是筛子法。

但是即使在VBA代码中,也还是有改进余地。

香川群子老师,拜读,研究中

TA的精华主题

TA的得分主题

发表于 2020-7-21 05:00 | 显示全部楼层
lee1892 发表于 2014-1-20 12:43
楼住的几个问题:

1、素性判定

老师您好!30位以内超大数的运算可以使用小数化处理吗?

TA的精华主题

TA的得分主题

发表于 2020-9-12 10:53 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
水刀梁 发表于 2020-7-21 05:00
老师您好!30位以内超大数的运算可以使用小数化处理吗?

不可以。小数计算是浮点运算,位数多了误差很大。

因此,只能采用整数运算。

VBA中,可以使用数字的CDec()格式运算,可以计算28位精度的整数。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-12-4 16:27 , Processed in 0.041586 second(s), 6 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表