均勻分布隨機函數的實現


前言

隨機函數就是產生數的函數,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();
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM