搜索
bottom↓
回复: 44

分享一个简易的随机数算法,请大家指正

[复制链接]

出0入0汤圆

发表于 2018-4-13 16:40:15 | 显示全部楼层 |阅读模式
用单片机生成随机数算法,伪随机,使用姚老板的12c5a60s2芯片,详情见文档
输入[0,65536)
输出[0,65536)
-
-
-
U16 rand65536( CU16 seed )/*2018.04.13Python+excel验证*/
{
        code U8 table[256] =
        {
                108,166,74,119,198,161,224,60,106,227,26,20,44,55,172,91,69,194,70,125,249,188,113,8,155,114,
                205,37,63,47,57,217,177,71,244,65,52,61,132,123,196,242,43,73,12,187,247,151,184,81,90,255,
                175,51,143,59,239,27,186,7,2,46,24,131,109,96,203,42,218,146,174,72,110,102,160,169,222,56,
                207,13,180,250,116,67,171,84,100,9,137,6,129,141,154,240,122,202,219,163,130,216,75,135,221,98,
                157,88,226,253,33,101,103,138,204,121,127,193,89,85,62,94,139,86,34,115,168,152,142,16,126,170,
                120,15,76,10,147,29,183,4,148,40,66,32,87,105,124,214,162,140,234,235,68,104,220,92,167,212,
                233,14,248,78,210,144,236,112,209,201,19,93,97,182,58,118,153,38,211,50,192,45,35,254,165,
                0,229,237,25,208,1,23,17,158,21,95,195,164,223,243,48,199,181,145,53,228,83,190,117,5,
                173,54,197,18,80,231,159,200,213,252,128,215,31,150,49,64,251,179,3,82,28,206,230,246,225,
                11,36,149,136,245,22,232,30,238,185,191,176,241,77,39,156,41,99,189,134,79,133,178,111,107
        };

        auto xdata U16 t1, t2;
        t1 = seed / 256;
        t2 = seed % 256;
       
        return( table[( t1 + t2 ) % 256 ] * 256 + table[ 255 - t2 ] );
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2018-4-13 16:41:26 | 显示全部楼层
附件上传

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入29汤圆

发表于 2018-4-13 16:44:52 | 显示全部楼层
这个是随机数生成器?
如果输入seed 的值每次都一样,输出的不都是一样的吗?

出0入0汤圆

 楼主| 发表于 2018-4-13 16:47:45 | 显示全部楼层
sunrn123 发表于 2018-4-13 16:44
这个是随机数生成器?
如果输入seed 的值每次都一样,输出的不都是一样的吗? ...

是的输入一样,输出一样,输入可以迭代嘛,比如递增或递减,达到输出不重复的伪随机数效果

出0入0汤圆

发表于 2018-4-13 16:49:57 | 显示全部楼层
这跟数组有啥区别?

出0入22汤圆

发表于 2018-4-13 16:50:42 | 显示全部楼层
shange144k8 发表于 2018-4-13 16:47
是的输入一样,输出一样,输入可以迭代嘛,比如递增或递减,达到输出不重复的伪随机数效果 ...

哈哈,输入一样输出一样还能叫随机吗,如果这样都能接受的话你写这函数干啥,直接用种子做索引查表就行了嘛,绕了个大弯多此一举

出0入0汤圆

 楼主| 发表于 2018-4-13 16:52:48 | 显示全部楼层
jcrorxp 发表于 2018-4-13 16:49
这跟数组有啥区别?

区别不大,相当于用256个元素实现65536个元素,当然如果再扣一层迭代可以实现更多的元素

出0入0汤圆

发表于 2018-4-13 16:53:11 | 显示全部楼层

出0入0汤圆

 楼主| 发表于 2018-4-13 16:55:10 | 显示全部楼层
jiaowoxiaolu 发表于 2018-4-13 16:50
哈哈,输入一样输出一样还能叫随机吗,如果这样都能接受的话你写这函数干啥,直接用种子做索引查表就行了 ...

嗯一开始我也想做数组索引,但要实现索引6万个元素,1是要代码空间,而是编辑这个6万字的文本太费劲

出0入0汤圆

发表于 2018-4-13 16:56:24 | 显示全部楼层
本帖最后由 lsfsxfljj 于 2018-4-13 16:58 编辑

真麻烦,弄个计数器让他跑,要数据的时候去取一下,随机了吧

出0入0汤圆

 楼主| 发表于 2018-4-13 16:58:30 | 显示全部楼层
lsfsxfljj 发表于 2018-4-13 16:56
真麻烦,弄个计算器让他跑,要数据的时候去取一下,随机了吧 ...

随机不重复,理论山真随机有重复的可能,这个随机不会重复

出0入0汤圆

发表于 2018-4-13 17:00:33 | 显示全部楼层
shange144k8 发表于 2018-4-13 16:58
随机不重复,理论山真随机有重复的可能,这个随机不会重复

随机也是在有限的集合内取出一个而已,你都定死了随什么机啊,弄个计数器最好了

出0入0汤圆

 楼主| 发表于 2018-4-13 17:02:51 | 显示全部楼层
lsfsxfljj 发表于 2018-4-13 17:00
随机也是在有限的集合内取出一个而已,你都定死了随什么机啊,弄个计数器最好了 ...

嗯,说的也是,又学到一个方法,

出0入0汤圆

发表于 2018-4-13 17:07:05 | 显示全部楼层
shange144k8 发表于 2018-4-13 17:02
嗯,说的也是,又学到一个方法,

是啊如果你这个数组是ADC引脚上的波动,那就差不多真是随机了.

出0入0汤圆

 楼主| 发表于 2018-4-13 17:14:15 | 显示全部楼层
jcrorxp 发表于 2018-4-13 17:07
是啊如果你这个数组是ADC引脚上的波动,那就差不多真是随机了.

是的,adc波动是个常规方法

出0入442汤圆

发表于 2018-4-13 18:22:35 来自手机 | 显示全部楼层
jcrorxp 发表于 2018-4-13 17:07
是啊如果你这个数组是ADC引脚上的波动,那就差不多真是随机了.

问题是好的adc能做到dc下95%恒定率,其余5%也就+-1。。。

出0入18汤圆

发表于 2018-4-13 18:29:13 | 显示全部楼层
ADC  读 最低位  每次只要最低位  采集 8次  就是一个 uint8 的随机数

出0入0汤圆

发表于 2018-4-13 22:04:55 | 显示全部楼层
利用stm32 内部 adc 产生随机数


//随机数初始化
void init_randSeed(unsigned int *seeds,int len)
{
    __IO  unsigned int seed=0;
    int i;
    for(i=0; i<len; i++)
    {
        seed|=(seeds[i]&0x01);
        seed<<=1;
    }
    srand(seed);
}
void init_adc()
{
    __IO          float Temper;
    unsigned int uhADCxConvertedValue[32];
    int i;
    for(i=0; i<32; i++)
    {
        if(HAL_ADC_Start(&hadc1) == HAL_OK)
        {
            HAL_ADC_PollForConversion(&hadc1, 30);
            uhADCxConvertedValue[i] = HAL_ADC_GetValue(&hadc1);
        }
                                //温度
        Temper = (uhADCxConvertedValue[i]*3300/4096-760)/2.5 + 25;
    }
    init_randSeed(uhADCxConvertedValue,32);
}

出0入0汤圆

发表于 2018-4-13 22:32:00 | 显示全部楼层
1、伪随机一般实在没办法取得随机种子的前提下才使用的。
2、随机种子一般可以从按键触发时间,ad随机采样,两个独立时钟差值产生。
比如可以用两个时钟源,最好是悬殊较大的时钟源,各自计数,随机数就直接从差值里面取,范围直接就是低几位

出0入0汤圆

 楼主| 发表于 2018-4-13 23:59:03 | 显示全部楼层
gongxd 发表于 2018-4-13 22:04
利用stm32 内部 adc 产生随机数

恩,很好的方法

出0入0汤圆

 楼主| 发表于 2018-4-14 00:02:26 | 显示全部楼层
shower.xu 发表于 2018-4-13 22:32
1、伪随机一般实在没办法取得随机种子的前提下才使用的。
2、随机种子一般可以从按键触发时间,ad随机采样 ...

如果都有随机种子了那就不需要随机数了,随机种子本生就是随机数,所以我对种子的理解就是种子连续

出0入0汤圆

发表于 2018-4-14 07:49:45 | 显示全部楼层
楼主在论坛里多检索一下,有很多实施的方案可以用,直接拿来就行了

C语言标准库自带的随机函数,在单片机上用的话,生成的数据不保证是唯一的,因为随机种子不一定唯一,如果保证随机种子唯一,生成随机数的方法rand()
可以直接用,那么现在随机种子的方法有以下两种

1.基于时间戳的随机
2.基于AD采样值的随机

出0入0汤圆

发表于 2018-4-14 08:11:19 | 显示全部楼层
这个叫随机数?还不如用标准库的那个

出140入8汤圆

发表于 2018-4-14 09:05:07 | 显示全部楼层
18楼的方法好用

出0入0汤圆

发表于 2018-4-14 09:17:08 | 显示全部楼层
计数器是个好办法

出0入0汤圆

发表于 2018-4-14 10:20:53 | 显示全部楼层
不知道什么情况要用随机数,什么 产品

出0入0汤圆

发表于 2018-4-14 10:36:03 | 显示全部楼层
用AD方法产生随机数还是比较常见的

出0入0汤圆

 楼主| 发表于 2018-4-14 15:50:47 | 显示全部楼层
磊磊映画 发表于 2018-4-14 07:49
楼主在论坛里多检索一下,有很多实施的方案可以用,直接拿来就行了

C语言标准库自带的随机函数,在单片机 ...

rand()函数产生的数貌似随机,但是如果种子相近随机也相近,时间戳和ad是真随机,但如果我要取6万个数,怎么能保证他们不重复呢

出0入0汤圆

 楼主| 发表于 2018-4-14 15:52:29 | 显示全部楼层
zuu0 发表于 2018-4-14 10:20
不知道什么情况要用随机数,什么 产品

等效于在屏幕上打印随机点,铺满某一个区域,且打点不重复,点的数量在6万个左右

出0入0汤圆

发表于 2018-4-14 18:39:14 | 显示全部楼层
弄一个256的表,弄一个计数器放在MAIN里计,要的时候取一下,在表里查一下,如果有相同的值就丢,再计一下

出0入0汤圆

发表于 2018-4-14 18:43:04 | 显示全部楼层
不相同就放表里,拿去用,完成了256个,把表清掉,,重头再来,这样是不是可以实现256个随机且不同的数了?

出0入0汤圆

 楼主| 发表于 2018-4-14 21:36:35 | 显示全部楼层
avrydy 发表于 2018-4-14 18:43
不相同就放表里,拿去用,完成了256个,把表清掉,,重头再来,这样是不是可以实现256个随机且不同的数了? ...

是啊基本就是这个道理,我的方法是用256个随机数实现65535个,使用了循环迭代保证了每次取出组合成不同的数值,就不用去比较了,要是逐个比较那运算量太大了,就这样跑65536个数都要0.67秒@22.1184mhz

出0入0汤圆

发表于 2018-4-16 09:02:25 | 显示全部楼层
shange144k8 发表于 2018-4-14 15:50
rand()函数产生的数貌似随机,但是如果种子相近随机也相近,时间戳和ad是真随机,但如果我要取6万个数 ...

时间戳肯定不会重复啊,时间戳是从1970年至今的秒计时数,最大范围至2的32次 幂,6W个不算什么

出0入0汤圆

 楼主| 发表于 2018-4-16 09:34:40 | 显示全部楼层
磊磊映画 发表于 2018-4-16 09:02
时间戳肯定不会重复啊,时间戳是从1970年至今的秒计时数,最大范围至2的32次 幂,6W个不算什么 ...

是啊,就是数太大,如果要把这个大数拿来去对应一个0~到6万以内的数,就有重复的可能

出0入0汤圆

 楼主| 发表于 2018-4-16 09:36:32 | 显示全部楼层
磊磊映画 发表于 2018-4-16 09:02
时间戳肯定不会重复啊,时间戳是从1970年至今的秒计时数,最大范围至2的32次 幂,6W个不算什么 ...

能贴具体代码来学习下么

出0入0汤圆

发表于 2018-4-16 10:07:33 | 显示全部楼层
shange144k8 发表于 2018-4-16 09:36
能贴具体代码来学习下么

u16 Adapter_GetRandSN(void)
{
    static u16 rand_SN=0;
    if(rand_SN==0) {
        srand(g_VendoutSerialNumberSeed);/*载入随机种子*/               
        rand_SN = rand();
        if(rand_SN ==0) rand_SN = 100;
    }

    return rand_SN++;
}



/**********************************
//名称:        SysTick_Handler
//功能:        系统滴答中断函数
//入口参数:        无
//出口参数:        无
**********************************/
void SysTick_Handler(void)
{
        
    g_VendoutSerialNumberSeed++; //出货流水号随机种子数
  
            
}

出0入0汤圆

发表于 2018-4-16 19:06:08 | 显示全部楼层
ADC是个好办法

出95入100汤圆

发表于 2018-4-16 19:25:34 | 显示全部楼层
shange144k8 发表于 2018-4-14 15:50
rand()函数产生的数貌似随机,但是如果种子相近随机也相近,时间戳和ad是真随机,但如果我要取6万个数 ...

随机和重复不是一个概念

出0入0汤圆

发表于 2018-4-16 19:31:12 | 显示全部楼层
本帖最后由 apple_eat 于 2018-4-16 19:33 编辑

标准库rand()函数的缺陷以及Blitz++随机数生成的简介
https://yq.aliyun.com/articles/226618

另外,有时候需要随机,但是概率可控,游戏中的暴率等等,涉及到问题就更复杂了.

出0入20汤圆

发表于 2018-4-16 21:21:11 | 显示全部楼层
N年前用80C31+RC振荡器+T1记脉冲个数做随机值。当时有内置的ADC就方便了。

出0入0汤圆

 楼主| 发表于 2018-4-16 22:47:12 | 显示全部楼层
lhj200304 发表于 2018-4-16 19:25
随机和重复不是一个概念

是的,不是一个概念

出0入0汤圆

 楼主| 发表于 2018-4-16 22:49:48 | 显示全部楼层
apple_eat 发表于 2018-4-16 19:31
标准库rand()函数的缺陷以及Blitz++随机数生成的简介
https://yq.aliyun.com/articles/226618

感谢,你提供的资料很有参考价值

出0入0汤圆

 楼主| 发表于 2018-4-16 22:50:43 | 显示全部楼层
mon51 发表于 2018-4-16 21:21
N年前用80C31+RC振荡器+T1记脉冲个数做随机值。当时有内置的ADC就方便了。

能简单描述一下用在什么产品中么

出0入0汤圆

发表于 2018-4-17 10:41:16 | 显示全部楼层
单片机生成随机数一直是一个比较麻烦的问题。

出0入0汤圆

发表于 2018-4-17 10:53:22 | 显示全部楼层
用AD生成随机数还真是好办法

出0入0汤圆

 楼主| 发表于 2018-4-17 19:14:58 | 显示全部楼层
ndust 发表于 2018-4-17 10:41
单片机生成随机数一直是一个比较麻烦的问题。

是的,走了不少弯路
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-29 04:04

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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