LOADING...
LOADING...
LOADING...
当前位置: 玩币族首页 > 行情分析 > 区块链中随机数的实现

区块链中随机数的实现

2020-03-16 智慧链技术社区 来源:区块链网络

我们生活的环境充满了随机性。一直以来运气,概率和命运这些概念都与随机性紧紧联系在一起。所有人类无法理解或无法预测的事物往往都被归类为随机事物。从生理上来说,我们也是沉浸在了随机海洋中。从云的运动到粒子和波浪的行为,随机性简直无处不在。

然而,尽管人类接触到了各种各样的随机事物,对随机性很熟悉,但依然难以将它转化为计算机可以使用的东西。当我们谈论计算机系统中的随机性时,我们真正指的是伪随机性,即尽可能模拟出现实世界应有的随机性,使之近乎于“真正的随机性”。以密码学安全伪随机数生成器为例,这是一个非常强大的随机性模拟。

随机数在隐私技术和密码学中发挥着重要作用。令人惊艳的是,通过生成一个随机数来对一条消息进行运算(XOR),提供了一种简单但十分强大的加密方案。即使是双方之间最简单的私人通信形式(即双方提前共享密钥的对称加密方案)也要求共享的密钥是随机的。如果此共享密钥不是随机的,则加密就毫无用处,因为任何知道密钥生成算法的人都可以确定密钥然后解密该条消息。

随机数的重要性不仅体现在安全通信渠道的建立上,还体现在确认通信对象上。如果多个人试图通过有限带宽的频道来互相通信,则可以利用随机数来确定频道携带消息的合理顺序。

随机数能够有效帮助团体或计算机达成一致协议或共识。区块链就是一个多方尝试就全局视角的某种更新达成一致(共识)的成功案例。更新通常在一轮内完成,也就是在一个周期性离散时间间隔内。

在互联网上,特定时间段内发送的消息数量是有上限的(即吞吐量或TPS),并且发送消息必将花去一定的时间( 即延迟),这都对共识造成了一定的限制。任何区块链共识协议的目标是在上述限制范围内达成一致协议。在公链上有数千个节点参与了区块链的维护,如果每个节点需要向所有其他节点发送消息并获得其反馈,那么网络的限制会大大增加达成共识的成本。这是因为在一轮时间内通过网络发送的消息数量太大。因此,为了确保共识,则需要通过减少在互联网上发送消息的数量来优化通信方案。

比特币达成此协议(中本聪共识)的方式是通过使用工作证明(PoW)作为随机数源来确定每一轮中哪一个区块将会被添加到区块链中,从而减少消息传递的费用。而WDC智慧链采用的DPOS(委托权益证明)协议,用于解决该问题的方法是根据持币者选择的15位代表(维护与管理区块链的节点),然后这些代表可以在网络限制内相互通信并及时达成一致。

为了公平选举出小组委员会的成员,保证没有人会提前知道成员的身份,WDC智慧链算法融入了无偏倚的随机数源。一旦该组验证者在两个区块上达成了一致,那个区块就会被广播给网络中的每一个人。

下面介绍几种简单的随机数的算法

1、 生成随机数

一般c语言中提供了随机数生成函数,

其一是伪随机数–rand:用于返回一个0-32767之间的伪随机数;

其二是随机种子函数–srand:用来初始化随机数发生器的随机种子

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main()

{

int i,j;

srand((int)time(0));

for (int i = 0; i < 10; i++)

{

for (int j = 0; j < 10; j++)

{

printf("%d ?",rand());

}

printf("\n");

}

return 0;

}

当然也可以生成一定范围内的随机数,比如生成0——100之间的随机数。

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main()

{

int i,j;

srand((int)time(0));

for (int i = 0; i < 10; i++)

{

for (int j = 0; j < 10; j++)

{

printf("%d ?",rand()*100/32767);

}

printf("\n");

}

return 0;

}

也可以生成100——200之间的随机数

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main()

{

int i,j;

srand((int)time(0));

for (int i = 0; i < 10; i++)

{

for (int j = 0; j < 10; j++)

{

printf("%d ?",rand()/1000+100);

}

printf("\n");

}

return 0;

}

使用rand()函数获取一定范围内的一个随机数,如果想要获取在一定范围内的数的话,直接做相应的除法取余即可。

#include<iostream>

#include<ctime>

using namespace std;

int main()

{

srand(time(0));

for(int i=0;i<10;i++)

{

//产生10以内的整数

cout<<rand()%10<<endl;

}

}

2 、生成[0,1]之间均匀分布的随机数算法

ri=mod(a?ri?1+b,base)

pi=ri/base

在这里采用第二种方式生成随机数。其中i=1,2,3.。。。而pi就是地推倒的第i个随机数,根据经验,一般选取基数base=256.0,一般为2的整数倍;另外的两个常数选取a=17.0 和b=139.0,需要注意:

(1)这里的取模运算是针对浮点型数据的,而c语言中的取模运算不能用于浮点数数据的操作,这样就需要用户自己编写取模的程序;

(2)ri是随着递推而每次更新的。因此,如果将这个算法编写出函数,需要考虑参数是传值还是传地址;

递推更新,所以在这里要传地址,否则得不到结果!

#include <stdio.h>

double rand0_1(double *r)

{

double base=256.0;

double a=17.0;

double b=139.0;

double temp1=a*(*r)+b;

//printf("%lf",temp1);

double temp2=(int)(temp1/base); //得到余数

double temp3=temp1-temp2*base;

//printf("%lf\n",temp2);

//printf("%lf\n",temp3);

*r=temp3;

double p=*r/base;

return p;

}

int main()

{

double r=5.0;

printf("output 10 number between 0 and 1:\n");

for (int i = 0; i < 10; i++)

{

printf("%10.5lf\n",rand0_1(&r));

}

return 0;

}

3 、产生任意范围内的随机数

比如产生[m,n]之间的随机数,这个很容易,只要将之前的[0,1]之间的随机数这样处理就行了,m+(m-n)*rand0_1(&r)就行了。

#include <stdio.h>

double rand0_1(double *r)

{

double base=256.0;

double a=17.0;

double b=139.0;

double temp1=a*(*r)+b;

//printf("%lf",temp1);

double temp2=(int)(temp1/base); //得到余数

double temp3=temp1-temp2*base;

//printf("%lf\n",temp2);

//printf("%lf\n",temp3);

*r=temp3;

double p=*r/base;

return p;

}

int main()

{

double m=1.0,n=5.0;

double r=5.0;

printf("output 10 number between 0 and 1:\n");

for (int i = 0; i < 10; i++)

{

printf("%10.5lf\n",m+(n-m)*rand0_1(&r));

}

return 0;

}

4、正态分布的随机数生成算法

符合正太分布的随机数在研究中也很重要,下面给出一种生成正态分布数的方法

random_normality=u+σ(∑Ri)?n/2n/12????√

其中Ri表示[0,1]之间均匀分布的随机数;u为均值,σ2为方差,当n趋向于无穷大的时候,得到随机的随机分布为正态分布;

#include <stdio.h>

#include <math.h>

double rand0_1(double *r)

{

double base=256.0;

double a=17.0;

double b=139.0;

double temp1=a*(*r)+b;

//printf("%lf",temp1);

double temp2=(int)(temp1/base); //得到余数

double temp3=temp1-temp2*base;

//printf("%lf\n",temp2);

//printf("%lf\n",temp3);

*r=temp3;

double p=*r/base;

return p;

}

double random_normality(double u,double t,double *r ,double n)

{

double total=0.0;

double result;

for (int i = 0; i < n; i++)

{

total+=rand0_1(r);

}

result=u+t*(total-n/2)/sqrt(n/12);

return result;

}

int main()

{

double r=5.0;

double u=2.0;

double t=3.5;

double n=12;

printf("output 10 number between 0 and 1:\n");

for (int i = 0; i < 10; i++)

{

printf("%10.5lf\n",random_normality(u,t,&r,n));

}

return 0;

}

补充知识点:leveldb中使用了一个简单的方式来实现随机化数;算法的核心是seed_ =(seed_ * A) % M,下面把源代码贴出来,不难,可以和上面的参考下

private:

uint32_t seed_;

public:

explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) {

// Avoid bad seeds.

if (seed_ == 0 || seed_ == 2147483647L) {

seed_ = 1;

}

}

uint32_t Next() {

static const uint32_t M = 2147483647L; ??// 2^31-1

static const uint64_t A = 16807; ?// bits 14, 8, 7, 5, 2, 1, 0

// We are computing

// ??????seed_ = (seed_ * A) % M, ???where M = 2^31-1

//

// seed_ must not be zero or M, or else all subsequent computed values

// will be zero or M respectively. ?For all other values, seed_ will end

// up cycling through every number in [1,M-1]

uint64_t product = seed_ * A;

// Compute (product % M) using the fact that ((x << 31) % M) == x.

seed_ = static_cast<uint32_t>((product >> 31) + (product & M));

// The first reduction may overflow by 1 bit, so we may need to

// repeat. ?mod == M is not possible; using > allows the faster

// sign-bit-based test.

if (seed_ > M) {

seed_ -= M;

}

return seed_;

}

// Returns a uniformly distributed value in the range [0..n-1]

// REQUIRES: n > 0

uint32_t Uniform(int n) { return Next() % n; }

// Randomly returns true ~"1/n" of the time, and false otherwise.

// REQUIRES: n > 0

bool OneIn(int n) { return (Next() % n) == 0; }

// Skewed: pick "base" uniformly from range [0,max_log] and then

// return "base" random bits. ?The effect is to pick a number in the

// range [0,2^max_log-1] with exponential bias towards smaller numbers.

uint32_t Skewed(int max_log) {

return Uniform(1 << Uniform(max_log + 1));

}

};

总之,做个简单的总结

C语言/C++怎样产生随机数:这里要用到的是rand()函数, srand()函数,和time()函数。

需要说明的是,iostream头文件中就有srand函数的定义,不需要再额外引入stdlib.h;而使用time()函数需要引入ctime头文件。

使用rand()函数获取一个随机数

如果你只要产生随机数而不需要设定范围的话,你只要用rand()就可以了:rand()会返回一随机数值, 范围在0至RAND_MAX 间。RAND_MAX定义在stdlib.h, 其值为2147483647。

使用rand函数和time函数

我们上面已经可以获取随机数了,为什么还需要使用time函数呢?我们通过多次运行发现,该程序虽然生成了10个随机数,但是这个10个随机数是固定的,也就是说并不随着时间的变化而变化。

这与srand()函数有关。srand()用来设置rand()产生随机数时的随机数种子。在调用rand()函数产生随机数前,必须先利用srand()设好随机数种子(seed), 如果未设随机数种子, rand()在调用时会自动设随机数种子为1。

上面的例子就是因为没有设置随机数种子,每次随机数种子都自动设成相同值1 ,进而导致rand()所产生的随机数值都一样。

srand()函数定义 :void srand (unsigned int seed);

通常可以利用geypid()或time(0)的返回值来当做seed

如果你用time(0)的话,要加入头文件#include

time(0)或者time(NULL)返回的是系统的时间(从1970.1.1午夜算起),单位:秒

参考:随机数生成算法

(https://www.cnblogs.com/ECJTUACM-873284962)

—-

编译者/作者:智慧链技术社区

玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。

LOADING...
LOADING...