前言
隨機函數就是產生數的函數,C語言里使用rand(),srand()等隨機函數實現隨機數生成。
函數簡介
int rand( void );
返回的是一個界於0~32767(0x7FFF)之間的偽隨機數,包括0和32767。
C預先生成一組隨機數,每次調用隨機函數時從指針所指向的位置開始取值,因此使用rand()重復運行程序產生的隨機數都是相同的,可以通過srand()函數來改變指針位置。
srand()會設置供rand()使用的隨機數種子。如果在第一次使用rand()之前沒有調用srand(),那么系統會自動調用srand()。而使用同種子相同的數調用 rand()會導致相同的隨機數序列被生成。
void srand( unsigned int seed );
改變隨機數表的指針位置(用seed變量控制)。
使用系統定時/計數器的值作為隨機種子。每個種子對應一組根據算法預先生成的隨機數,所以,在相同的平台環境下,不同時間產生的隨機數會是不同的,相應的,若將srand(unsigned)time(NULL)改為srand(TP)(TP為任一常量),則無論何時運行、運行多少次得到的“隨機數”都會是一組固定的序列,因此srand生成的隨機數是偽隨機數。
一般配合time(NULL)使用,因為時間每時每刻都在改變,產生的seed值都不同。
場景
使用rand函數生成的隨機數嚴格滿足正態分布。而在很多時候,我們希望隨機數的生成不要滿足正態分布,特別是在處理網絡通信報文的時候。
例如,我們需要在交換機處理到海量報文時,能夠使遠端的從設備盡可能的分段同時向局端回應報文,以減輕局部報文處理壓力。
均勻分布隨機函數實現
開發環境
實現步驟
1)打開Qt Creater,創建GUI工程
2)在mainwindow.h中添加函數聲明
void paintEvent(QPaintEvent *);
3)在mainwindow.cpp中添加函數實現
導入頭文件
#include <QPainter>
實現void paintEvent(QPaintEvent *)函數
/* *Qt中函數paintEvent(QPaintEvent*)是被系統自動調用。 *paintEvent(QPaintEvent *)函數是QWidget類中的虛函數,用於ui的繪制,會在多種情況下被其他函數自動調用。 */ void MainWindow::paintEvent(QPaintEvent *) { QPainter painter(this); QPen pen; //畫筆 pen.setColor(QColor(255,0,0)); //設置畫筆顏色 painter.setPen(pen); //添加畫筆 long int r[kSum] = {0}; int i = 0; int j = 0; do{ r[i] = Uniform(0, 300); i++; }while(i < kSum); while((j + 30) < (kSum + 30)){ painter.drawPoint(j, r[j]); j++; } }
4)添加隨機函數實現代碼
#include <stdio.h> #include <stdlib.h> #include <time.h> #define kSum 1000 //算法一 /* *均勻分布隨機函數均勻化 */ double _uniform(double min, double max, long int *seed) { double t = 0; *seed = 2045 * (*seed) + 1; *seed = *seed - (*seed / 1048576) * 1048576; t = (*seed) / 1048576.0; t = min + (max - min) * t; return t; } /* *均勻分布隨機函數產生隨機數 */ long int Uniform(double min, double max) { long int s = 0; double r = 0; //srand((unsigned int)time(NULL)); /*同一個時間種子可能會從產生相同的隨機數列*/ s = rand(); r = _uniform(min, max, &s); return ((long int)r); } //算法二 double AverageRandom(double min, double max) { int minInteger = (int)(min * 10000); int maxInteger = (int)(max * 10000); int randInteger = rand() * rand(); int diffInteger = maxInteger - minInteger; int resultInteger = randInteger % diffInteger + minInteger; return (resultInteger/10000.0); }
實現效果
小結
從圖中可以看出,使用上述函數生成的隨機數符合均勻分布。
本案例主要使用了Qt的繪圖功能,用來直觀展示生成隨機數的效果。檢驗隨機函數生成隨機數的效果。
附錄
最后附上該算法實現的全部代碼:
//mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); void paintEvent(QPaintEvent *); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
//mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include <QPainter> #include <stdio.h> #include <stdlib.h> #include <time.h> #define kSum 1000 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } /* *均勻分布隨機函數均勻化 */ double _uniform(double min, double max, long int *seed) { double t = 0; *seed = 2045 * (*seed) + 1; *seed = *seed - (*seed / 1048576) * 1048576; t = (*seed) / 1048576.0; t = min + (max - min) * t; return t; } /* *均勻分布隨機函數產生隨機數 */ long int Uniform(double min, double max) { long int s = 0; double r = 0; //srand((unsigned int)time(NULL)); /*同一個時間種子可能會從產生相同的隨機數列*/ s = rand(); r = _uniform(min, max, &s); return ((long int)r); } /* *Qt中函數paintEvent(QPaintEvent*)是被系統自動調用。 *paintEvent(QPaintEvent *)函數是QWidget類中的虛函數,用於ui的繪制,會在多種情況下被其他函數自動調用。 */ void MainWindow::paintEvent(QPaintEvent *) { QPainter painter(this); QPen pen; //畫筆 pen.setColor(QColor(255,0,0)); //設置畫筆顏色 painter.setPen(pen); //添加畫筆 long int r[kSum] = {0}; int i = 0; int j = 0; do{ r[i] = Uniform(0, 300); i++; }while(i < kSum); while((j + 30) < (kSum + 30)){ painter.drawPoint(j, r[j]); j++; } }
//main.cpp #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }