shange144k8 发表于 2018-4-13 16:40:15

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

用单片机生成随机数算法,伪随机,使用姚老板的12c5a60s2芯片,详情见文档
输入[0,65536)
输出[0,65536)
-
-
-
U16 rand65536( CU16 seed )/*2018.04.13Python+excel验证*/
{
        code U8 table =
        {
                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 ] );
}

shange144k8 发表于 2018-4-13 16:41:26

附件上传

sunrn123 发表于 2018-4-13 16:44:52

这个是随机数生成器?
如果输入seed 的值每次都一样,输出的不都是一样的吗?

shange144k8 发表于 2018-4-13 16:47:45

sunrn123 发表于 2018-4-13 16:44
这个是随机数生成器?
如果输入seed 的值每次都一样,输出的不都是一样的吗? ...

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

jcrorxp 发表于 2018-4-13 16:49:57

这跟数组有啥区别?

jiaowoxiaolu 发表于 2018-4-13 16:50:42

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

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

shange144k8 发表于 2018-4-13 16:52:48

jcrorxp 发表于 2018-4-13 16:49
这跟数组有啥区别?

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

a312835782 发表于 2018-4-13 16:53:11

{:sweat:}{:sweat:}{:sweat:}{:sweat:}{:sweat:}{:sweat:}

shange144k8 发表于 2018-4-13 16:55:10

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

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

lsfsxfljj 发表于 2018-4-13 16:56:24

本帖最后由 lsfsxfljj 于 2018-4-13 16:58 编辑

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

shange144k8 发表于 2018-4-13 16:58:30

lsfsxfljj 发表于 2018-4-13 16:56
真麻烦,弄个计算器让他跑,要数据的时候去取一下,随机了吧 ...

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

lsfsxfljj 发表于 2018-4-13 17:00:33

shange144k8 发表于 2018-4-13 16:58
随机不重复,理论山真随机有重复的可能,这个随机不会重复

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

shange144k8 发表于 2018-4-13 17:02:51

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

嗯,说的也是,又学到一个方法,{:handshake:}

jcrorxp 发表于 2018-4-13 17:07:05

shange144k8 发表于 2018-4-13 17:02
嗯,说的也是,又学到一个方法,

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

shange144k8 发表于 2018-4-13 17:14:15

jcrorxp 发表于 2018-4-13 17:07
是啊如果你这个数组是ADC引脚上的波动,那就差不多真是随机了.

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

wye11083 发表于 2018-4-13 18:22:35

jcrorxp 发表于 2018-4-13 17:07
是啊如果你这个数组是ADC引脚上的波动,那就差不多真是随机了.

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

dengxiaofeng 发表于 2018-4-13 18:29:13

ADC读 最低位每次只要最低位采集 8次就是一个 uint8 的随机数

gongxd 发表于 2018-4-13 22:04:55

利用stm32 内部 adc 产生随机数


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

shower.xu 发表于 2018-4-13 22:32:00

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

shange144k8 发表于 2018-4-13 23:59:03

gongxd 发表于 2018-4-13 22:04
利用stm32 内部 adc 产生随机数




恩,很好的方法

shange144k8 发表于 2018-4-14 00:02:26

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

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

磊磊映画 发表于 2018-4-14 07:49:45

楼主在论坛里多检索一下,有很多实施的方案可以用,直接拿来就行了

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

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

zhugean 发表于 2018-4-14 08:11:19

这个叫随机数?还不如用标准库的那个

leiyitan 发表于 2018-4-14 09:05:07

18楼的方法好用

richards 发表于 2018-4-14 09:17:08

计数器是个好办法

zuu0 发表于 2018-4-14 10:20:53

不知道什么情况要用随机数,什么 产品

电子小生 发表于 2018-4-14 10:36:03

用AD方法产生随机数还是比较常见的

shange144k8 发表于 2018-4-14 15:50:47

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

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

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

shange144k8 发表于 2018-4-14 15:52:29

zuu0 发表于 2018-4-14 10:20
不知道什么情况要用随机数,什么 产品

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

avrydy 发表于 2018-4-14 18:39:14

弄一个256的表,弄一个计数器放在MAIN里计,要的时候取一下,在表里查一下,如果有相同的值就丢,再计一下

avrydy 发表于 2018-4-14 18:43:04

不相同就放表里,拿去用,完成了256个,把表清掉,,重头再来,这样是不是可以实现256个随机且不同的数了?

shange144k8 发表于 2018-4-14 21:36:35

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

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

磊磊映画 发表于 2018-4-16 09:02:25

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

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

shange144k8 发表于 2018-4-16 09:34:40

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

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

shange144k8 发表于 2018-4-16 09:36:32

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

能贴具体代码来学习下么{:handshake:}

磊磊映画 发表于 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++; //出货流水号随机种子数

            
}

fenxiang1103 发表于 2018-4-16 19:06:08

ADC是个好办法

lhj200304 发表于 2018-4-16 19:25:34

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

随机和重复不是一个概念

apple_eat 发表于 2018-4-16 19:31:12

本帖最后由 apple_eat 于 2018-4-16 19:33 编辑

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

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

mon51 发表于 2018-4-16 21:21:11

N年前用80C31+RC振荡器+T1记脉冲个数做随机值。当时有内置的ADC就方便了。

shange144k8 发表于 2018-4-16 22:47:12

lhj200304 发表于 2018-4-16 19:25
随机和重复不是一个概念

是的,不是一个概念

shange144k8 发表于 2018-4-16 22:49:48

apple_eat 发表于 2018-4-16 19:31
标准库rand()函数的缺陷以及Blitz++随机数生成的简介
https://yq.aliyun.com/articles/226618



感谢,你提供的资料很有参考价值{:handshake:}

shange144k8 发表于 2018-4-16 22:50:43

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

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

ndust 发表于 2018-4-17 10:41:16

单片机生成随机数一直是一个比较麻烦的问题。

69879 发表于 2018-4-17 10:53:22

用AD生成随机数还真是好办法

shange144k8 发表于 2018-4-17 19:14:58

ndust 发表于 2018-4-17 10:41
单片机生成随机数一直是一个比较麻烦的问题。

是的,走了不少弯路
页: [1]
查看完整版本: 分享一个简易的随机数算法,请大家指正