ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[讨论] 生成不重复随机整数的各种算法 - 加生成结果的简单检验

[复制链接]

TA的精华主题

TA的得分主题

发表于 2011-2-5 20:34 | 显示全部楼层 |阅读模式
本帖已被收录到知识树中,索引项:其他结构和算法
原帖的大量讨论在这里,由于楼层太多几乎没人看下去,而且楼主已经弃楼,所以再开一帖方便继续讨论

生成不重复随机数的一段代码
http://club.excelhome.net/redire ... 300&ptid=676313

总结题目:
从一个指定的范围m,生成指定数量n个不重复随机整数,等于从范围内的m个整数,随机抽样n个,然后随机排序

许多算法都用了洗牌算法,其优缺点如下:
优点是:速度很快,实现也很简单。

缺点是:洗牌算法似乎只能打乱一个已经存在的序列,而不能保证随机从范围内抽样。
我发现洗牌一次肯定不能达到随机抽样,抽样的均值和标准差都离数学期望值相当远

目前最快的三个算法如下:
lsftest提出的分段生成+洗牌,也有上述缺点,我发现除非至少洗牌两次,否则抽样很不均匀,结果导致整个VBA的速度也没有理论上的快了

Zamyi提出的根据当前随机整数,按平均步长,等概率生成下一个随机整数
在抽样很少(<50)的时候会出错,而且抽样结果严重偏差
但是在抽样很多的时候却没啥问题,速度一样很快,而且可能是限制了步长取值的原因,生成的结果甚至比其余算法更加平均

最后,我提出的把整个抽样范围看作大蛋糕,随机分给每个抽样,这个算法似乎也可以均匀抽取,然后洗牌一次打乱顺序就可以了。

其实这三个算法的速度差异可以忽略,算法都是O(n)乘以常数,绝对可以保证每分钟抽样千万以上,够用了。

不过简单验证随机性和均匀性的VBA程序,还需要继续深入设计,说不定还能挖掘出某些算法特别之处,也进一步确保结果的均匀性和随机性。

[ 本帖最后由 灰袍法师 于 2011-2-5 21:59 编辑 ]

VBA - 生成不重复随机整数的各种方法 + 简单统计检验.rar

97.14 KB, 下载次数: 419

TA的精华主题

TA的得分主题

发表于 2011-2-7 12:30 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助

〖Excel Home友情提示〗

   

很遗憾通知楼上朋友,您的帖子在24小时之内没有任何回复!

通常情况下,本论坛发布的主题帖会在8小时被回复或处理。您的帖子在24小时之内未被回复,其中的原因可能是

1、问题表述不清、模棱两可,难以理解,帮助者被搞晕了,夺帖而出;
2、没有上传必要的附件,或附件被遗忘在某个角落;
3、发帖提问时,语气带棱角、带挑衅,不幸被列入不受欢迎的帖子;
4、所提问题不成立,或提不合理的要求,乐于助人者使出“走为上”之计;
5、话题较偏、较冷或者发布到了不合适的版块,暂时无人问津,顾影自怜。


为了提高您的问题解决效率,我们推荐您阅读以下文章:
* 如何发表新话题和上传附件:http://club.excelhome.net/thread-45649-1-1.html
* 发帖的技巧:http://club.excelhome.net/thread-176339-1-1.html
* EH技术论坛的最佳学习方法:http://club.excelhome.net/thread-117862-1-1.html

TA的精华主题

TA的得分主题

发表于 2011-4-17 23:26 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2012-2-23 21:11 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
支持法师了。法师是高人。

TA的精华主题

TA的得分主题

发表于 2012-8-2 12:23 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
非常感谢法师,对我很有帮助,谢谢了

TA的精华主题

TA的得分主题

发表于 2012-8-2 12:31 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2014-5-5 09:07 | 显示全部楼层
法师,利用字典实现随机数的去重不是很方便吗?过一会再研究一下……

TA的精华主题

TA的得分主题

发表于 2014-8-28 22:11 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
aoe1981 发表于 2014-5-5 09:07
法师,利用字典实现随机数的去重不是很方便吗?过一会再研究一下……

我很早以前就研究过此问题。

只是没有公开发布而已。

今天正好看到此贴,就正式发布一下。
  1. Sub kagawa() '指定区间内 均匀随机取不重复值 按指定列数输出
  2. '    Dim a, b, c(), d, f(), h, i, l, m, n, r, t '因为数值个数会超Long范围,所以不应该定义数据类型
  3.    
  4.     d = [d2] '小数位数d 用法同=Round(,numdecimalplaces)的第2参数 零为整数、正数为小数、负数为个十百千位向上取整
  5.     a = [a2] * 10 ^ d '取值下限、自动按小数位设置扩大/缩小
  6.     b = [b2] * 10 ^ d '取值上限、自动按小数位设置扩大/缩小
  7.     m = [c2] '取值个数 F2单元格中公式计算取值允许个数 =IF(E2,INT((B2-A2)*10^D2/E2)+1,"无限")
  8.     h = [e2] '最小间隔步长 h=0时允许重复。而h不为零时如取值个数大于取数范围则取数不足部分返回=0
  9.     l = [g2] '输出时列数指定 行数自动=m\l
  10.     r = [h2] '输出时是否排序 r=0时返回随机乱序(数组洗牌法)、r=1时按从小到大升序输出
  11.    
  12.     Randomize
  13.     ReDim c(m - 1) '按取值个数定义存放结果的数组c
  14.     If b - a < m * h Then c(0) = a Else c(0) = Int(((b - a + 1) / m - h) * Rnd) + a '首位取值*Rnd即可
  15. '    n = 0 当前取值个数
  16.     Do
  17.         If b - c(n) < (m - n) * h Then
  18.             If c(n) + h > b Then Exit Do Else c(n + 1) = c(n) + h
  19.         Else
  20.             c(n + 1) = c(n) + Int(((b - c(n) + 1) / (m - n) - h) * Rnd * 2) + h
  21.             '取数原理为: 上个值c(n) + 剩余范围(b - c(n) + 1) 除以剩余个数(m - n)得到的均匀区间
  22.             '             并扣除最小间隔h然后 乘以2倍随机数 Rnd*2 取值  再加上最小间隔h
  23.             '其中关键是 要乘以2倍随机数 Rnd*2 取值 这是因为Rnd的期望平均值=0.5
  24.         End If
  25.         n = n + 1
  26.     Loop Until n = m - 2 '到剩下最后一个时停止 (因最后一个的计算方法不同)
  27.     If c(n) + h <= b Then c(m - 1) = c(n) + Int((b - c(n) + 1 - h) * Rnd) + h '末位取值*Rnd即可
  28.    
  29.     ReDim f(m \ l, l - 1) '按指定列数计算所需行数后定义存放结果的数组f
  30.     If r = 0 Then 'r=0时返回随机乱序(数组洗牌法)
  31.         For i = 0 To m - 1
  32.             r = Int((m - i) * Rnd) + i '数组洗牌算法进行不重复随机乱序抽取
  33.             t = c(r): c(r) = c(i): c(i) = c(r) '抽取后进行位置交换 保证不重复以及无遗漏
  34.             f(i \ l, i Mod l) = t / 10 ^ d '结果按指定小数位换算
  35.         Next
  36.     Else 'r=1时按从小到大升序输出
  37.         For i = 0 To m - 1
  38.             f(i \ l, i Mod l) = c(i) / 10 ^ d '结果按指定小数位换算
  39.         Next
  40.     End If
  41.    
  42.     [a5].CurrentRegion.Offset(1) = ""
  43.     [a6].Resize(m \ l + 1, l) = f '按指定列数输出结果
  44.    
  45. End Sub
复制代码


香川巨量随机取数20140828.rar (22.55 KB, 下载次数: 84)



评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2015-3-28 20:59 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-22 04:17 , Processed in 0.036323 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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