怎么产生一个真正的随即数

时间:2022-01-20 12:49:14

请教什么算法能真正产生随机数(和我投掷筛子一样随机)?

45 个解决方案

#1


基本不可能, 计算机产生的都是伪随机数

#2


用rand()
函数可以吧??

#3


1.模拟一次随机事件
2.利用无理数

PS:rand()是伪随机数

#4


自己随便写个数进去就是随机数了,或者查随机数表~~

#5


利用计算机不太可能得到真正的随机数;
目前计算机上用的是伪随机数吧

不过,linux系统是收集硬件噪音产生随机数,这算不算 真正的随机数呢?

等待楼下高人前来回答

#6


你怎么能证明这个结果是随机的?

#7


有用于随机数随机程度的算法的.
5楼的做法无法证明.

#8


引用 3 楼 baihacker 的回复:
1.模拟一次随机事件 
2.利用无理数 

PS:rand()是伪随机数


可是怎么模拟呢?

#9


刚才搜到这篇文章:

           Analysis of the Linux Random Number Generator
                                Zvi Gutterman                                           Benny Pinkas
         Safend and The Hebrew University of Jerusalem                              University of Haifa
                                                 Tzachy Reinman
                                    The Hebrew University of Jerusalem
                                                  March 6, 2006
                                                       Abstract
    Linux is the most popular open source project. The Linux random number generator is part of the kernel of all
Linux distributions and is based on generating randomness from entropy of operating system events. The output of
this generator is used for almost every security protocol, including TLS/SSL key generation, choosing TCP sequence
numbers, and file system and email encryption. Although the generator is part of an open source project, its source
code (about 2500 lines of code) is poorly documented, and patched with hundreds of code patches.
    We used dynamic and static reverse engineering to learn the operation of this generator. This paper presents a
description of the underlying algorithms and exposes several security vulnerabilities. In particular, we show an attack
on the forward security of the generator which enables an adversary who exposes the state of the generator to compute
previous states and outputs. In addition we present a few cryptographic flaws in the design of the generator, as well
as measurements of the actual entropy collected by it, and a critical analysis of the use of the generator in Linux
distributions on disk-less devices.

看来不能算真正的随机数。

#10


引用 8 楼 birchlin 的回复:
引用 3 楼 baihacker 的回复:
1.模拟一次随机事件 
2.利用无理数 

PS:rand()是伪随机数 
 

可是怎么模拟呢?

一个箱子里面有10个号码(0-9)
无穷个人去取,取了又放回去

#11


引用 8 楼 birchlin 的回复:
引用 3 楼 baihacker 的回复:
1.模拟一次随机事件
2.利用无理数

PS:rand()是伪随机数


可是怎么模拟呢?

估计一下整个系统运行中大概需要多少随机数,然后选择一个随机数生成程序就是了

#12


只要加入了人为的控制因素,比如计算公式,各种条件等等,就不可能产生真正的随机数!我们所得到的随机数都是可以再现的,因而不时真正意义上的随机数,而只是伪随机数而已

#13


引用 12 楼 uestcshe 的回复:
只要加入了人为的控制因素,比如计算公式,各种条件等等,就不可能产生真正的随机数!我们所得到的随机数都是可以再现的,因而不时真正意义上的随机数,而只是伪随机数而已

这种说法可能有点问题,比如咱俩组成一个随机数生成器,如下运作
1. 电脑一边的你打开一个文本文档,切换到编辑模式,闭上眼睛,手指在键盘上乱拍;
2. 电脑另一边的我随机一个时间给你一个电话,你听到电话声音响起的时候,停止拍键盘;
3. 将文本文档的最后一个字符作为产生的随机数。

算不算完全随机的呢?

#14


其实真实与虚拟都是一线之隔,计算机发展到足以模拟整个世界的时候,哈哈
说不定人类是哪个文明做出的模拟机,它们一边在外空间看人类活动,一边说,怎么模拟度这么差,到底能不能完全随机呢~~

#15



#include <iostream.h>
#include <stdlib.h>
#include <time.h>
void main()
{
int num;
srand(time(NULL));//产生随即种子
for (int i=0;i<10;i++)
{
num=rand(); //产生随机数
cout<<num<<'\t';
}
cout<<endl;
}

#16


真正的随机应该是不可能的。

#17


楼上忘记薛定谔的那只猫咪了么?

#18


我的意思是指,原子的衰变,是真正的随机

#19


你每次XXOO的坚持时间,精确到毫秒,取末尾数就是随机的。

#20


丢骰子吧

#21


15楼那样不行么 

每次以系统时间设定种子后产生随机数 

应该是随机的吧 

#22


15楼那样不可以么

每次以系统时间设定随机数种子

然后再rand()随机数 这样不算真正随机数么

#23


rand()

#24


其实,如果生成随机数有100种算法的话,这种算法不是倒数第一就是倒数第二

#25


同意楼上的
大部分商用嵌入式软件的随机数算法都是自己写的

#26


使用cpu电压,当前屏幕数据,当前鼠标位置等信息产生种子,再用这个种子生成随机数

#27


还有当前时间

#28


看来产生真正的随机数很难,(难道只能有上帝产生?)

所以我来这里求助?

我在程序里就是用的15楼的算法,但是产生的是一样的结果.如下:

for (int i=0;i<10;i++)
   m_rand();//输出的10个完全一样的结果

m_rand()//15楼的代码
{
srand(time(NULL));//产生随即种子
    for (int i=0;i<10;i++)
    {    
        num=rand(); //产生随机数
        cout<<num<<'\t';
    }
    cout<<endl;
srand(time(NULL));//产生随即种子
    for (int i=0;i<10;i++)
    {    
        num=rand(); //产生随机数
        cout<<num<<'\t';
    }
    cout<<endl;
19楼的 办法我也考虑过,有两个问题
1 不知道系统的时间能不能精确到豪秒(我的是一般的电脑)
2 即使精确到了豪秒,如果在for (int i=0;i<10;i++)一次循环的时间少于1豪秒,我觉得用这种办法也不行

26楼的思路和19楼存在同样的问题

希望大虾指教!

#29



#include <iostream.h>
#include <stdlib.h>
#include <time.h>
void main()
{
    static unsigned int i=0;
    int num;
    srand(++i+time(NULL));//产生随即种子
    for (int i=0;i<10;i++)
    {    
        num=rand(); //产生随机数
        cout<<num<<'\t';
    }
    cout<<endl;
}

#30


其实这个是数学问题。。

#31


产生随机长度(1-100)随机的字符串(只包括数字,字母(大写或者小写))

#include <stdlib.h>
#include <stdio.h>
#include <time.h>           //使用当前时钟做种子

void main(void)
{
srand((unsigned)time(NULL));          //初始化随机数
int l,len = (rand()%100+1);
char *p,*s= (char*)malloc(len+1);
p = s;
l = len;
char probability,chr;
while(l-- >0)
{
probability = rand()%(26+26+10); 
if(probability<26)
chr = (char)(rand()%26+0x41);
else if(probability<52)
chr = (char)(rand()%26+0x61);
else
chr = (char)(rand()%10+0x30);
*(p++) = chr;
}
*p='\0';
printf("Len= %d  ,  s= %s\n%d\n",len,s,rand());
free(s);
}

#32


楼主,Kruth曾经建议过一个程序,不是基于线性同余而是以相减为基础方法的,可靠性还是比较高的,执行速度也是不错,发在下边,你参考下
貌似在这里我发了好几次了
$ cat ran.h
#ifndef RAN_H_INCLUDED
#define RAN_H_INCLUDED

//return a real number that subject to
//          x ~ U(0,1)
long double ran();

#endif // RAN_H_INCLUDED

$ cat ran.cpp
#include "ran.h"

#include <ctime>

static long double _ran( int& seed );

long double ran()
{
    static int seed = static_cast < unsigned int >( time( NULL ) );
    return _ran( seed );
}

//from  Numerical Recipes in C
static long double _ran( int& seed )
{

    const int MBIG = 1000000000;
    const int MSEED = 161803398;
    const int MZ = 0;
    const long double FAC = 1.0E-9L;

    static int inext, inextp;
    static long ma[56];
    static int iff = 0;
    long mj, mk;
    int i, ii, k;

    if ( seed < 0 || iff == 0)
    {
        iff = 1;
        mj = MSEED - (seed < 0 ? -seed : seed);
        mj %= MBIG;
        ma[55] = mj;
        mk = 1;
        for (i = 1; i <= 54; i++) {
            ii = (21 * i) % 55;
            ma[ii] = mk;
            mk = mj - mk;
            if (mk < MZ)
                mk += MBIG;
            mj = ma[ii];
        }
        for (k = 1; k <= 4; k++)
            for (i = 1; i <= 55; i++)
            {
                ma[i] -= ma[1 + (i + 30) % 55];
                if (ma[i] < MZ)
                    ma[i] += MBIG;
            }
        inext = 0;
        inextp = 31;
        seed = 1;
    }
    if (++inext == 56)
        inext = 1;
    if (++inextp == 56)
        inextp = 1;
    mj = ma[inext] - ma[inextp];
    if (mj < MZ)
        mj += MBIG;
    ma[inext] = mj;
    return mj * FAC;
}

#33


引用 3 楼 baihacker 的回复:
1.模拟一次随机事件 
2.利用无理数 

PS:rand()是伪随机数

支持

#34


28楼
以下程序获得系统毫秒级别的时间
并且将系统时间(以毫秒为单位)传给随机种子srand(tp.millitm);

[color=#FF0000]请教怎么模拟一次随机事件 [/color]

#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>

#include <time.h>           //使用当前时钟做种子
#include <sys/timeb.h>
#include <windows.h>

void m_rand()

int num=0;
int i;

struct timeb tp;
struct tm *tm;
static unsigned short lastmillsec;

ftime(&tp);

while(lastmillsec == tp.millitm)//保证这次的时间(毫秒)与上次不一样
{
Sleep(1);
ftime(&tp);
}

lastmillsec = tp.millitm;
#if 1
tm=localtime(&(tp.time));
cout<<tm->tm_hour<<":"<<tm->tm_min<<":"<<tm->tm_sec<<":"<<tp.millitm<<endl;
#endif
srand(tp.millitm);// 将系统时间(以毫秒为单位)传给随机种子srand(tp.millitm);
//产生随机种子 
    for(i=0;i <10;i++) 
    {    
num=rand(); //产生随机数
        cout <<num <<'\t'; 
    } 
    cout <<endl;
}

void main(void)
{
for(int i=0;i <10;i++) 
  m_rand();//输出的10组不一样的结果 
}

#35


该回复于2008-06-14 19:26:31被版主删除

#36


你能证明“投掷筛子”是真正随机的?

#37


引用 36 楼 iambic 的回复:
你能证明“投掷筛子”是真正随机的? 


哈哈,如果不出老千,就是随机的,概率书上有的

#38


只要是程序生成的,就一定是伪随机数

#39


该回复于2008-06-14 19:26:30被版主删除

#40


>哈哈,如果不出老千,就是随机的,概率书上有的
概率书怎么证明的?

#41


引用 38 楼 WuBill 的回复:
只要是程序生成的,就一定是伪随机数

#42


不可能的,随机因子 必须 自己设定. 

#43


srand(time(NULL));//产生随即种子
rand();

#44


想在计算机里产生真正的随机数基本是不可能的,只不过看随即的程度而已。在北大出的一本统计计算书里面有好多产生随机数的方法,楼主要是有兴趣不妨看一下

#45


15楼的方法 是比较可行的 

#1


基本不可能, 计算机产生的都是伪随机数

#2


用rand()
函数可以吧??

#3


1.模拟一次随机事件
2.利用无理数

PS:rand()是伪随机数

#4


自己随便写个数进去就是随机数了,或者查随机数表~~

#5


利用计算机不太可能得到真正的随机数;
目前计算机上用的是伪随机数吧

不过,linux系统是收集硬件噪音产生随机数,这算不算 真正的随机数呢?

等待楼下高人前来回答

#6


你怎么能证明这个结果是随机的?

#7


有用于随机数随机程度的算法的.
5楼的做法无法证明.

#8


引用 3 楼 baihacker 的回复:
1.模拟一次随机事件 
2.利用无理数 

PS:rand()是伪随机数


可是怎么模拟呢?

#9


刚才搜到这篇文章:

           Analysis of the Linux Random Number Generator
                                Zvi Gutterman                                           Benny Pinkas
         Safend and The Hebrew University of Jerusalem                              University of Haifa
                                                 Tzachy Reinman
                                    The Hebrew University of Jerusalem
                                                  March 6, 2006
                                                       Abstract
    Linux is the most popular open source project. The Linux random number generator is part of the kernel of all
Linux distributions and is based on generating randomness from entropy of operating system events. The output of
this generator is used for almost every security protocol, including TLS/SSL key generation, choosing TCP sequence
numbers, and file system and email encryption. Although the generator is part of an open source project, its source
code (about 2500 lines of code) is poorly documented, and patched with hundreds of code patches.
    We used dynamic and static reverse engineering to learn the operation of this generator. This paper presents a
description of the underlying algorithms and exposes several security vulnerabilities. In particular, we show an attack
on the forward security of the generator which enables an adversary who exposes the state of the generator to compute
previous states and outputs. In addition we present a few cryptographic flaws in the design of the generator, as well
as measurements of the actual entropy collected by it, and a critical analysis of the use of the generator in Linux
distributions on disk-less devices.

看来不能算真正的随机数。

#10


引用 8 楼 birchlin 的回复:
引用 3 楼 baihacker 的回复:
1.模拟一次随机事件 
2.利用无理数 

PS:rand()是伪随机数 
 

可是怎么模拟呢?

一个箱子里面有10个号码(0-9)
无穷个人去取,取了又放回去

#11


引用 8 楼 birchlin 的回复:
引用 3 楼 baihacker 的回复:
1.模拟一次随机事件
2.利用无理数

PS:rand()是伪随机数


可是怎么模拟呢?

估计一下整个系统运行中大概需要多少随机数,然后选择一个随机数生成程序就是了

#12


只要加入了人为的控制因素,比如计算公式,各种条件等等,就不可能产生真正的随机数!我们所得到的随机数都是可以再现的,因而不时真正意义上的随机数,而只是伪随机数而已

#13


引用 12 楼 uestcshe 的回复:
只要加入了人为的控制因素,比如计算公式,各种条件等等,就不可能产生真正的随机数!我们所得到的随机数都是可以再现的,因而不时真正意义上的随机数,而只是伪随机数而已

这种说法可能有点问题,比如咱俩组成一个随机数生成器,如下运作
1. 电脑一边的你打开一个文本文档,切换到编辑模式,闭上眼睛,手指在键盘上乱拍;
2. 电脑另一边的我随机一个时间给你一个电话,你听到电话声音响起的时候,停止拍键盘;
3. 将文本文档的最后一个字符作为产生的随机数。

算不算完全随机的呢?

#14


其实真实与虚拟都是一线之隔,计算机发展到足以模拟整个世界的时候,哈哈
说不定人类是哪个文明做出的模拟机,它们一边在外空间看人类活动,一边说,怎么模拟度这么差,到底能不能完全随机呢~~

#15



#include <iostream.h>
#include <stdlib.h>
#include <time.h>
void main()
{
int num;
srand(time(NULL));//产生随即种子
for (int i=0;i<10;i++)
{
num=rand(); //产生随机数
cout<<num<<'\t';
}
cout<<endl;
}

#16


真正的随机应该是不可能的。

#17


楼上忘记薛定谔的那只猫咪了么?

#18


我的意思是指,原子的衰变,是真正的随机

#19


你每次XXOO的坚持时间,精确到毫秒,取末尾数就是随机的。

#20


丢骰子吧

#21


15楼那样不行么 

每次以系统时间设定种子后产生随机数 

应该是随机的吧 

#22


15楼那样不可以么

每次以系统时间设定随机数种子

然后再rand()随机数 这样不算真正随机数么

#23


rand()

#24


其实,如果生成随机数有100种算法的话,这种算法不是倒数第一就是倒数第二

#25


同意楼上的
大部分商用嵌入式软件的随机数算法都是自己写的

#26


使用cpu电压,当前屏幕数据,当前鼠标位置等信息产生种子,再用这个种子生成随机数

#27


还有当前时间

#28


看来产生真正的随机数很难,(难道只能有上帝产生?)

所以我来这里求助?

我在程序里就是用的15楼的算法,但是产生的是一样的结果.如下:

for (int i=0;i<10;i++)
   m_rand();//输出的10个完全一样的结果

m_rand()//15楼的代码
{
srand(time(NULL));//产生随即种子
    for (int i=0;i<10;i++)
    {    
        num=rand(); //产生随机数
        cout<<num<<'\t';
    }
    cout<<endl;
srand(time(NULL));//产生随即种子
    for (int i=0;i<10;i++)
    {    
        num=rand(); //产生随机数
        cout<<num<<'\t';
    }
    cout<<endl;
19楼的 办法我也考虑过,有两个问题
1 不知道系统的时间能不能精确到豪秒(我的是一般的电脑)
2 即使精确到了豪秒,如果在for (int i=0;i<10;i++)一次循环的时间少于1豪秒,我觉得用这种办法也不行

26楼的思路和19楼存在同样的问题

希望大虾指教!

#29



#include <iostream.h>
#include <stdlib.h>
#include <time.h>
void main()
{
    static unsigned int i=0;
    int num;
    srand(++i+time(NULL));//产生随即种子
    for (int i=0;i<10;i++)
    {    
        num=rand(); //产生随机数
        cout<<num<<'\t';
    }
    cout<<endl;
}

#30


其实这个是数学问题。。

#31


产生随机长度(1-100)随机的字符串(只包括数字,字母(大写或者小写))

#include <stdlib.h>
#include <stdio.h>
#include <time.h>           //使用当前时钟做种子

void main(void)
{
srand((unsigned)time(NULL));          //初始化随机数
int l,len = (rand()%100+1);
char *p,*s= (char*)malloc(len+1);
p = s;
l = len;
char probability,chr;
while(l-- >0)
{
probability = rand()%(26+26+10); 
if(probability<26)
chr = (char)(rand()%26+0x41);
else if(probability<52)
chr = (char)(rand()%26+0x61);
else
chr = (char)(rand()%10+0x30);
*(p++) = chr;
}
*p='\0';
printf("Len= %d  ,  s= %s\n%d\n",len,s,rand());
free(s);
}

#32


楼主,Kruth曾经建议过一个程序,不是基于线性同余而是以相减为基础方法的,可靠性还是比较高的,执行速度也是不错,发在下边,你参考下
貌似在这里我发了好几次了
$ cat ran.h
#ifndef RAN_H_INCLUDED
#define RAN_H_INCLUDED

//return a real number that subject to
//          x ~ U(0,1)
long double ran();

#endif // RAN_H_INCLUDED

$ cat ran.cpp
#include "ran.h"

#include <ctime>

static long double _ran( int& seed );

long double ran()
{
    static int seed = static_cast < unsigned int >( time( NULL ) );
    return _ran( seed );
}

//from  Numerical Recipes in C
static long double _ran( int& seed )
{

    const int MBIG = 1000000000;
    const int MSEED = 161803398;
    const int MZ = 0;
    const long double FAC = 1.0E-9L;

    static int inext, inextp;
    static long ma[56];
    static int iff = 0;
    long mj, mk;
    int i, ii, k;

    if ( seed < 0 || iff == 0)
    {
        iff = 1;
        mj = MSEED - (seed < 0 ? -seed : seed);
        mj %= MBIG;
        ma[55] = mj;
        mk = 1;
        for (i = 1; i <= 54; i++) {
            ii = (21 * i) % 55;
            ma[ii] = mk;
            mk = mj - mk;
            if (mk < MZ)
                mk += MBIG;
            mj = ma[ii];
        }
        for (k = 1; k <= 4; k++)
            for (i = 1; i <= 55; i++)
            {
                ma[i] -= ma[1 + (i + 30) % 55];
                if (ma[i] < MZ)
                    ma[i] += MBIG;
            }
        inext = 0;
        inextp = 31;
        seed = 1;
    }
    if (++inext == 56)
        inext = 1;
    if (++inextp == 56)
        inextp = 1;
    mj = ma[inext] - ma[inextp];
    if (mj < MZ)
        mj += MBIG;
    ma[inext] = mj;
    return mj * FAC;
}

#33


引用 3 楼 baihacker 的回复:
1.模拟一次随机事件 
2.利用无理数 

PS:rand()是伪随机数

支持

#34


28楼
以下程序获得系统毫秒级别的时间
并且将系统时间(以毫秒为单位)传给随机种子srand(tp.millitm);

[color=#FF0000]请教怎么模拟一次随机事件 [/color]

#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>

#include <time.h>           //使用当前时钟做种子
#include <sys/timeb.h>
#include <windows.h>

void m_rand()

int num=0;
int i;

struct timeb tp;
struct tm *tm;
static unsigned short lastmillsec;

ftime(&tp);

while(lastmillsec == tp.millitm)//保证这次的时间(毫秒)与上次不一样
{
Sleep(1);
ftime(&tp);
}

lastmillsec = tp.millitm;
#if 1
tm=localtime(&(tp.time));
cout<<tm->tm_hour<<":"<<tm->tm_min<<":"<<tm->tm_sec<<":"<<tp.millitm<<endl;
#endif
srand(tp.millitm);// 将系统时间(以毫秒为单位)传给随机种子srand(tp.millitm);
//产生随机种子 
    for(i=0;i <10;i++) 
    {    
num=rand(); //产生随机数
        cout <<num <<'\t'; 
    } 
    cout <<endl;
}

void main(void)
{
for(int i=0;i <10;i++) 
  m_rand();//输出的10组不一样的结果 
}

#35


该回复于2008-06-14 19:26:31被版主删除

#36


你能证明“投掷筛子”是真正随机的?

#37


引用 36 楼 iambic 的回复:
你能证明“投掷筛子”是真正随机的? 


哈哈,如果不出老千,就是随机的,概率书上有的

#38


只要是程序生成的,就一定是伪随机数

#39


该回复于2008-06-14 19:26:30被版主删除

#40


>哈哈,如果不出老千,就是随机的,概率书上有的
概率书怎么证明的?

#41


引用 38 楼 WuBill 的回复:
只要是程序生成的,就一定是伪随机数

#42


不可能的,随机因子 必须 自己设定. 

#43


srand(time(NULL));//产生随即种子
rand();

#44


想在计算机里产生真正的随机数基本是不可能的,只不过看随即的程度而已。在北大出的一本统计计算书里面有好多产生随机数的方法,楼主要是有兴趣不妨看一下

#45


15楼的方法 是比较可行的