打印
[应用相关]

C语言 将产生的随机数存入数组,数据不能相同

[复制链接]
3258|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhuomuniao110|  楼主 | 2016-4-30 21:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1.定义一个一维数,数组大小为24。
2.产生0~23的随机数。
3.将产生的随机数存入i数组,要求数组中的每个数据不能相同。
4.补充说明,这个子程序要求每次调用后,这个数组里面就 存放了0~23这些数据,而且这些数据没有重复的。
5.注意,C语言有随机数函数,可以用函数产生随机数。RAND(N)

#include <stdio.h>
#include <time.h>
#define ArrayMaxItem 24
int RandTest()
{
        int i = 0;
        int ret = 0;
        time_t t;
        for (i=0; i<10; i++)
        {
                srand((unsigned) time(&t)*10);
                ret = rand();
                //ret = rand((unsigned) time(&t));
                printf("ret:%d\n", ret);
        }
        return 0;
}
int RandArray(int *a, int n)
{
        int i = 0;
        int t = 0;
        time_t mytime;
        struct tm *timeinfo;
        for (i=0; i<n ;i++)
                a = 0;
        /*only n-1 posions need to by seted*/
        for (i=0; i<n-1; i++)
        {
                while(a[t=rand((unsigned)time(&mytime))%n] != 0);
                a[t] = n-i-1;
                timeinfo = localtime(&mytime);
                printf("time:%s a[%d]:%d\n", asctime(timeinfo), t, a[t]);
        }
        for (i=0; i<n; i++)
        {
                printf("a[%d]:%d\n", i, a);
        }
        return 0;
}
int main()
{
        int a[ArrayMaxItem];
        RandArray(a, ArrayMaxItem);
        //RandTest();
        return 0;
}

1.随机数的使用过程:
  网上说要先调用srand(unsigned seed)函数设置随机数种子,再调用rand(void)产生随机数,但我用系统时间来作为种子,产生了十次随机数值都是一样的。
  之后采用上面代码所用的方法,直接将种子传入rand()函数中,调用十次产生不同的值,但每次调用产生的值是同一组

2.获得系统时间:
#include <stdio.h>
#include <time.h>   
int main()
{  
time_t rawtime;  
struct tm * timeinfo;  
time ( &rawtime );  
timeinfo = localtime ( &rawtime );  
printf ( "The current date/time is: %s", asctime (timeinfo) );  

return 0;
}
time_t // 时间类型(time.h 定义)
struct tm {    // 时间结构,time.h 定义如下:  
int tm_sec;  
        int tm_min;  
        int tm_hour;  
        int tm_mday;  
        int tm_mon;  
        int tm_year;  
        int tm_wday;  
        int tm_yday;  
        int tm_isdst;  
        }  
        time ( &rawtime );   // 获取时间,以秒计,从1970年1月一日起算,存于rawtime  
        localtime ( &rawtime );   //转为当地时间,tm 时间结构  
asctime()   // 转为标准ASCII时间格式:  
//就是直接打印tm,tm_year 从1900年计算,所以要加1900,月tm_mon,从0计算,所以要加1

3.思路:
  用随机数产生0~n-1范围内的数组下标,当对应的数不为0,则置为n-i-1,这样,只需要置n-1个,最后一个本来就是0。
  产生0~n-1范围内的随机数的方法是对rand()产生出来的随机数对n取余。

4.运行结果:
time:Tue Apr 19 12:28:42 2016
a[7]:23
time:Tue Apr 19 12:28:42 2016
a[22]:22
time:Tue Apr 19 12:28:42 2016
a[9]:21
time:Tue Apr 19 12:28:42 2016
a[19]:20
time:Tue Apr 19 12:28:42 2016
a[17]:19
time:Tue Apr 19 12:28:42 2016
a[10]:18
time:Tue Apr 19 12:28:42 2016
a[12]:17
time:Tue Apr 19 12:28:42 2016
a[13]:16
time:Tue Apr 19 12:28:42 2016
a[2]:15
time:Tue Apr 19 12:28:42 2016
a[11]:14
time:Tue Apr 19 12:28:42 2016
a[18]:13
time:Tue Apr 19 12:28:42 2016
a[4]:12
time:Tue Apr 19 12:28:42 2016
a[16]:11
time:Tue Apr 19 12:28:42 2016
a[8]:10
time:Tue Apr 19 12:28:42 2016
a[15]:9
time:Tue Apr 19 12:28:42 2016
a[21]:8
time:Tue Apr 19 12:28:42 2016
a[14]:7
time:Tue Apr 19 12:28:42 2016
a[6]:6
time:Tue Apr 19 12:28:42 2016
a[5]:5
time:Tue Apr 19 12:28:42 2016
a[1]:4
time:Tue Apr 19 12:28:42 2016
a[23]:3
time:Tue Apr 19 12:28:42 2016
a[20]:2
time:Tue Apr 19 12:28:42 2016
a[3]:1
a[0]:0
a[1]:4
a[2]:15
a[3]:1
a[4]:12
a[5]:5
a[6]:6
a[7]:23
a[8]:10
a[9]:21
a[10]:18
a[11]:14
a[12]:17
a[13]:16
a[14]:7
a[15]:9
a[16]:11
a[17]:19
a[18]:13
a[19]:20
a[20]:2
a[21]:8
a[22]:22
a[23]:3

沙发
lxyppc| | 2016-4-30 22:22 | 只看该作者
本帖最后由 lxyppc 于 2016-4-30 22:23 编辑

楼主一定不打牌

使用特权

评论回复
板凳
mintspring| | 2016-4-30 23:21 | 只看该作者
不知道这种随机到底是真的随机还是假的,如果重新运行一次,的到的序列还是一样的吗

使用特权

评论回复
地板
xyz549040622| | 2016-5-1 09:02 | 只看该作者
mintspring 发表于 2016-4-30 23:21
不知道这种随机到底是真的随机还是假的,如果重新运行一次,的到的序列还是一样的吗 ...

随机只是个伪随机。

使用特权

评论回复
5
whtwhtw| | 2016-5-1 10:37 | 只看该作者
用ad转换悬空脚,得到白噪声随机数

使用特权

评论回复
6
hgjinwei| | 2016-5-1 20:58 | 只看该作者
楼主没有明白C提供的rand的使用方法,rand需要先使用srand(seed)设置随机种子,不然,如果采用缺省种子,程序将每次运行(启动)都是一样样的。种子只要设置一次就够了,后面无需重复设置。
rand是个伪随机算法,相同的种子,得到的随机序列是一样的。所以srand时,才有采用系统时钟的说法,因为,系统时钟是我们最容易得到的一个时变值(当然,这个随机并不怎么可靠,攻击者可以相对轻松地得到这个种子,从而得到随机序列)。

还有,楼主都不考虑程序运行效率的,一个"while(a[t=rand((unsigned)time(&mytime))%n] != 0);",将浪费多少CPU宝贵时间啊。还好,程序只要求得到24个值,要是240,2400,甚至更多,那么CPU得在这个循环中浪费许多资源。因为,随机仅仅表示“下一个不可预知”,并不表示下一个不会和之前的重复。如果要得到一个足够大的无重复随机序列,这段函数有可能直接就死机了。

以下是参考(运行于Windows)

void RandArray(int *a, int n)
{
    int     i;
    int     r;


    for(i = 0; i < n; i++){
        a[i] = i;
    }

    while(i > 0){
        r = rand() % i;
        i -= 1;
        if(r != i){
            int t = a[i]; a[i] = a[r]; a[r] = t;
        }
    }
}


int main(int argc, char *argv[])
{
    int     j,k;
    int     a[24];


    srand(GetTickCount());
    while(1){
        RandArray(a,24);

        printf("result:");
        for(j = 0; j < 24; j++){
            printf(" %02d", a[j]);
            for(k = j+1; k < 24; k++){
                if(a[j] == a[k]){
                    printf("\r\nError: a[%u] == a[%u] = %02X\r\n", j,k,a[j]);
                    break;
                }
            }
        }
        printf("\r\n");
        Sleep(1000);
    }
}
):

使用特权

评论回复
7
cnb12345| | 2016-5-2 11:56 | 只看该作者

使用特权

评论回复
8
mintspring| | 2016-5-5 10:42 | 只看该作者
xyz549040622 发表于 2016-5-1 09:02
随机只是个伪随机。

是的,我测试了这个函数,每次生成的数组都一样。

使用特权

评论回复
9
mintspring| | 2016-5-5 14:26 | 只看该作者
hgjinwei 发表于 2016-5-1 20:58
楼主没有明白C提供的rand的使用方法,rand需要先使用srand(seed)设置随机种子,不然,如果采用缺省种子,程 ...

原来如此,一直不知道为何总是这样,多谢大侠指点绝招。

使用特权

评论回复
10
zhuomuniao110|  楼主 | 2016-5-8 19:50 | 只看该作者
一个小小的随机都这么多学问。看来基础和理论要扎实才行。

使用特权

评论回复
11
ideafor| | 2016-5-8 20:35 | 只看该作者
mintspring 发表于 2016-4-30 23:21
不知道这种随机到底是真的随机还是假的,如果重新运行一次,的到的序列还是一样的吗 ...

用过MATLAB里面的随机数函数,好像每次运行都不一样
C语言里面的这个就不好说了

使用特权

评论回复
12
hgjinwei| | 2016-5-9 11:14 | 只看该作者
6 楼的程序存在以下问题:
1、BUG,没有对rand的返回做非负数判断,如果返回负数,程序将出错;
2、边界问题,最后一个数据无法和其他数据交换,无需再随机选择处理;

使用特权

评论回复
13
jar1866| | 2016-5-9 15:06 | 只看该作者
#define   STDLIB_A        16807  /* Multiplier */
#define   STDLIB_M   2147483647
#define   STDLIB_Q       (STDLIB_M / STDLIB_A)
#define   STDLIB_R       (STDLIB_M % STDLIB_A)

static long seed = 1;

int rand (void)
{
  long  hi, lo;
  unsigned int tmp;

  hi = seed / STDLIB_Q;
  lo = seed % STDLIB_Q;
  seed = (STDLIB_A * lo) - (STDLIB_R * hi);
  if (seed <= 0) {
    seed += STDLIB_M;
  }
  tmp = (unsigned int) seed & 0x7FFFU;
  return (int) tmp;
} /* end rand */

void srand (unsigned int init)
{
  seed = (long)init;
} /* end srand */

这是freescale的随机数实现,仅供参考
可以把本次生成随机数作为下一次生成的种子,就能实现比较好的随机数组成的数组,你要0-23,
只要将结果%23即可

使用特权

评论回复
14
icecut| | 2016-5-9 15:13 | 只看该作者
你可以试试用硬件随机数生成器.

使用特权

评论回复
15
_summer| | 2016-5-9 16:51 | 只看该作者
学习学习

使用特权

评论回复
16
zhuomuniao110|  楼主 | 2016-5-11 21:53 | 只看该作者
硬件随机数发生器?有这个东西吗

使用特权

评论回复
17
mintspring| | 2016-5-15 12:02 | 只看该作者
ideafor 发表于 2016-5-8 20:35
用过MATLAB里面的随机数函数,好像每次运行都不一样
C语言里面的这个就不好说了 ...

恩,对,我直接运行那个函数,每次都一样,刚开始不懂,坑死人。

使用特权

评论回复
18
9990| | 2016-5-21 12:31 | 只看该作者
像这样的随机队列根本不需要开队列缓冲区,否则要生成一个很大的队列,但是RAM资源比较紧张时怎么办

使用特权

评论回复
19
zhuomuniao110|  楼主 | 2016-5-22 23:16 | 只看该作者
也可以根据时间函数求一个随机数。

使用特权

评论回复
20
auv555| | 2016-5-23 16:21 | 只看该作者
斜体字看的好累心。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

206

主题

3358

帖子

10

粉丝