论坛首页 Java版 OO

彩票选号后的数学——抽牌算法的实现

浏览 17497 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
最后更新时间:2008-07-06
甜菜侯爵 写道
Nighthaven 写道
甜菜侯爵 写道
Nighthaven 写道
那么考虑效率的话,应该是做36位二进制数中恰好有5个1出现的数字的全排列,将排列编号,每次随机的时候,就从编号总数中随机出来一个。我表达清楚了没?

这样就只要一次随机,也不需要容器或者数组。


您表达的非常清楚。
不过还要拜托您能详细解答一下,毕竟我还只是个小虾米,对全排列还只是似懂非懂的状态,36位二进制数的全排列就更甭说了。不知您这种算法是怎么圈定取值范围的(比如我希望从50~100中取它25个不重复的数字出来),还是只能用于36选5?再有一个恕我这个小虾米不太明白的地方就是您这个“恰好有5个1出现的数字的全排列”是不是不需要计算,英特尔的CPU里或者微软操作系统里就已经自带这么个可维护表了,我什么时候想用直接拿过来查就是?


不是“那么考虑效率”的问题,而是用ArrayList来这样取不重复的随机数,数据量达到一定程度就不行了,我测试到100万取50万就已经挂掉了,而原来的算法用时只3秒多而已。

全排列可以预先算好存起来(要效率就存代码里,不要效率就存文件里),空间换时间么。
0一直+1加到36个1为止不就是全排列么~~~判断这之中哪些是恰好有5个1的数虽然也要费点时间,但是并不是在你的抽签程序里,而是可以单独写一个程序另外算的(或者在网上搜搜?也许有无聊的人已经算过了?),反正只需要算一次(顶多用几秒钟吧)。

当然,对于你这种100万级的程序,可能就不能用基本类型的数了。不过,做全排列然后随机序号的方法还是可行的。当然这个全排列的生成可能就比较费时间了,但是反正是只要计算一次,算个几天应该也可以的。当然坏处就是如果你改变了参数,还要重新算~呃,需要占用的存储空间也是越来越大地~

其实2的36次方个++对于只需要算一次的程序来说也不是很多。
不过刚才想了一下,对于你的100万选50万来说,生成全排列应该是需要非常猛的cpu和非常的大的内存了(假设写在内存里)



这是我的算法还是您的算法?您这样说是想挖苦谁,讽刺什么?
取不重复的随机数这种问题就一定只会是彩票选取这样的小数据量运算么?

在您发帖子之前,哪怕是幼稚,至少所有人还是在认真讨论一种算法,而在您的全排列算法闪亮登场后,在您的大内存,猛CPU的强烈攻势下,这种讨论氛围已经荡然无存了。

算了,我也知道您的意思,讽刺也好、挖苦也罢,无非是想说我杀鸡用了牛刀,为这样的小问题费不上如此大费周折地讨论一番所谓的“效率”。

好,好,好,您也算是第一个带星的JavaEye朋友给我回复,如此待客之道,在下受教了。

啊?我有挖苦你讽刺你么?最后一句话的意思只是在承认我的算法对超大数据量并不适用!
这下我是真无语了。
   
0 请登录后投票
最后更新时间:2008-07-06
让其他人评述吧。
   
0 请登录后投票
最后更新时间:2008-07-07
hax 写道
甜菜侯爵 写道
很简单的一个小算法,抛砖引玉了。

这的确是一种解决方法,但是会有很大的问题,比如说5选4吧,前三个都已经选好了是2,3,4,现在取第4个数,这种情况下,取到1和5的几率要比取到2,3,4的几率还要小,也就是说,最坏的情况下,有可能会取很多次2,3,4,扔掉很多次,才最终能取到1或5,完成4个随机数字的选择。显然,这样效率是有很大问题的。



明显站不住脚,5选4等价于5选1,根本用不着多此一举。


同意,楼主对随机的理解有些错误
   
0 请登录后投票
最后更新时间:2008-07-07
你这个算法含量太底,该算发核心在于取随机数。
   
0 请登录后投票
最后更新时间:2008-07-07
甜菜侯爵 写道
让其他人评述吧。

你俩打架吧,嘎嘎
   
0 请登录后投票
最后更新时间:2008-07-07

def List getRandomElements(List list, int count) {
    def result = new ArrayList(count)
    def random = new Random()
    int c = count
    count.times {
        int i = random.nextInt(c)
        result.add(list.remove(i))
        c--
    }
    return result
}

def initList(List list) {
    1000000.times {
        list[it] = it
    }
}

def timer(Closure closure) {
    def start = System.currentTimeMillis()
    closure.call()
    def end = System.currentTimeMillis()
    println end - start
}

def testList = new LinkedList()
initList testList

timer {
    println(getRandomElements(testList, 1000))
}

   
0 请登录后投票
最后更新时间:2008-07-07
性能关键词:

ArrayList
LinkedList
size()
   
0 请登录后投票
最后更新时间:2008-07-08
import random

total_number = 36
range_number = 7
takeone = []
while len(takeone) < range_number:
    temp = random.randint(1,total_number)
    if not temp in takeone: takeone.append(temp)
takeone.sort()
print takeone
   
0 请登录后投票
最后更新时间:2008-07-08
跟我的想法类似
   
0 请登录后投票
最后更新时间:2008-07-08
上面有人说的很对啊,没必要一个数一个数的列举!36选7一共有36*35*34*33*32*31*30/7*6*5*4*3*2*1(记为n)种组合可能,把所有可能都放到一个ArrayList里(记为list),在[0, n-1]里取一个随机整数k,list.get(k)就是一个随机的彩票号码
   
0 请登录后投票
论坛首页 Java版 OO

跳转论坛:
JavaEye推荐