老师给出产生随机数的.h文件。
/*******************************************************************************
RandNum.h: interface for the CRandNum class.
********************************************************************************/
#include
/*************************************************************************
Designed by Xiao Ma ([email protected]), Sun Yat-sen University.
This program can only be employed for academic research.
*************************************************************************/
#if !defined(AFX_RANDNUM_H__72FEDEAF_A51C_4724_9A53_5F2F5E00CED4__INCLUDED_)
#define AFX_RANDNUM_H__72FEDEAF_A51C_4724_9A53_5F2F5E00CED4__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CRandNum
{
public:
CRandNum();
virtual ~CRandNum();
};
/************************************************************************
*************************************************************************
The following generator employs the linear-congruential method,
and specifically uses a choice of multiplier that was proposed
as a standard by Stephen K. Park et al. in "Technical correspondence,"
Communications of the ACM36(1993), number 7, 108-110
*************************************************************************
************************************************************************/
class CLCRandNum
{
public:
CLCRandNum();
virtual ~CLCRandNum();
void SetSeed(int flag);
void PrintState(FILE *fp);
double Uniform();
void Normal(double *nn, int len_nn);
private:
long int state;
static const int A;
static const long M;
static const int Q;
static const int R;
};
/************************************************************************
*************************************************************************
The following generator employs the Wichman-Hill algorithm
*************************************************************************
************************************************************************/
class CWHRandNum
{
public:
CWHRandNum();
virtual ~CWHRandNum();
void SetSeed(int flag);
void PrintState(FILE *fp);
double Uniform();
void Normal(double *nn, int len_nn);
private:
int X, Y, Z;
};
#endif // !defined(AFX_RANDNUM_H__72FEDEAF_A51C_4724_9A53_5F2F5E00CED4__INCLUDED_)
产生随机数的.cpp文件
/********************************************************************************
RandNum.cpp: implementation of the CRandNum class.
********************************************************************************/
/*******************************************************************************
Programmed by Xiao Ma, Sun Yat-sen University.
If you have any suggestions, please contact me at [email protected]
The program can only be employed for academic research.
******************************************************************************/
#include "RandNum.h"
#include
#include
#include
#include
#include
#include
/********************************************************************
Construction/Destruction
*********************************************************************/
CRandNum::CRandNum()
{
}
CRandNum::~CRandNum()
{
}
/**********************************************************************************
***********************************************************************************
The following generator employs the linear-congruential method,
and specifically uses a choice of multiplier that was proposed
as a standard by Stephen K. Park et al. in "Technical correspondence,"
Communications of the ACM36(1993), number 7, 108-110
***********************************************************************************
***********************************************************************************/
/*******************************************************************************
Construction/Destruction
*******************************************************************************/
CLCRandNum::CLCRandNum()
{
}
CLCRandNum::~CLCRandNum()
{
}
/*******************************************************************
定义一些常数
*******************************************************************/
const int CLCRandNum::A = 48271;
const long CLCRandNum::M = 2147483647;
const int CLCRandNum::Q = M / A;
const int CLCRandNum::R = M % A;
/******************************************************************
函数:SetSeed(int flag)
功能:为随机数设置种子
输入参数:flag
flag = -1 -----默认种子
flag = 0 -----随机种子
flag = 1 -----自选种子
******************************************************************/
void CLCRandNum::SetSeed(int flag)
{
if (flag < 0)
state = 17;
else if (flag == 0){
state = 0;
while (state == 0){
srand((unsigned)time(NULL));
state = rand();
}
}
else {
fprintf(stdout, "\nEnter the initial state: ");
fscanf_s(stdin, "%ld", &state, sizeof(long));
}
return;
}
/**************************************************************************
函数:PrintState(FILE *fp)
功能:向文件中输出种子值
输入参数:文件指针
**************************************************************************/
void CLCRandNum::PrintState(FILE *fp)
{
fprintf(fp, "\n***init_state = %ld***\n", state);
return;
}
/**************************************************************************
函数:Uniform()
功能:产生0-1间均匀分布的随机数
***************************************************************************/
double CLCRandNum::Uniform()
{
double u;
int tmpState = A * (state % Q) - R * (state / Q);
if (tmpState >= 0)
state = tmpState;
else
state = tmpState + M;
u = state / (double)M;
return u;
}
/***************************************************************************
函数:Normal(double *nn, int len_nn)
功能:产生长为len_nn的服从均值为0,方差为1的正态分布的随机数
输入参数:
len_nn ----- 随机数长度
输出参数
*nn ----- 保存产生的随机数
****************************************************************************/
void CLCRandNum::Normal(double *nn, int len_nn)
{
double x1, x2, w;
int t;
for (t = 0; 2 * t + 1 < len_nn; t++){
w = 2.0;
while (w > 1.0){
x1 = 2.0 * Uniform() - 1.0;
x2 = 2.0 * Uniform() - 1.0;
w = x1 * x1 + x2 * x2;
}
w = sqrt(-2.0 * log(w) / w);
nn[2 * t] = x1 * w;
nn[2 * t + 1] = x2 * w;
}
if (len_nn % 2 == 1){
w = 2.0;
while (w > 1.0){
x1 = 2.0 * Uniform() - 1.0;
x2 = 2.0 * Uniform() - 1.0;
w = x1 * x1 + x2 * x2;
}
w = sqrt(-2.0 * log(w) / w);
nn[len_nn - 1] = x1 * w;
}
}
/***************************************************************************
**************************************************************************
The following generator employs the Wichman-Hill algorithm
****************************************************************************
***************************************************************************/
/*******************************************************************************
Construction/Destruction
*******************************************************************************/
CWHRandNum::CWHRandNum()
{
}
CWHRandNum::~CWHRandNum()
{
}
/******************************************************************
函数:SetSeed(int flag)
功能:为随机数设置种子
输入参数:flag
flag = -1 -----默认种子
flag = 0 -----随机种子
flag = 1 -----自选种子
******************************************************************/
void CWHRandNum::SetSeed(int flag)
{
if (flag < 0){
X = 13;
Y = 37;
Z = 91;
}
else if (flag == 0){
X = 0;
Y = 0;
Z = 0;
while (X == 0 || Y == 0 || Z == 0){
srand((unsigned)time(NULL));
X = rand();
Y = rand();
Z = rand();
}
}
else {
fprintf(stdout, "\nEnter the initial state (X Y Z): ");
fscanf_s(stdin, "%d %d %d", &X, sizeof(int), &Y, sizeof(int), &Z, sizeof(int));
}
return;
}
/**************************************************************************
函数:PrintState(FILE *fp)
功能:向文件中输出种子值
输入参数:文件指针
**************************************************************************/
void CWHRandNum::PrintState(FILE *fp)
{
fprintf(fp, "\n***init_state (X Y Z) = %d %d %d***\n", X, Y, Z);
return;
}
/**************************************************************************
函数:Uniform()
功能:产生0-1间均匀分布的随机数
***************************************************************************/
double CWHRandNum::Uniform()
{
double U;
X = 171 * X % 30269;
Y = 172 * Y % 30307;
Z = 170 * Z % 30323;
U = X / 30269.0 + Y / 30307.0 + Z / 30323.0;
U = U - int(U);
return U;
}
/***************************************************************************
函数:Normal(double *nn, int len_nn)
功能:产生长为len_nn的服从均值为0,方差为1的正态分布的随机数
输入参数:
len_nn ----- 随机数长度
输出参数
nn ----- 保存产生的随机数
****************************************************************************/
void CWHRandNum::Normal(double *nn, int len_nn)
{
double x1, x2, w;
int t;
for (t = 0; 2 * t + 1 < len_nn; t++){
w = 2.0;
while (w > 1.0){
x1 = 2.0 * Uniform() - 1.0;
x2 = 2.0 * Uniform() - 1.0;
w = x1 * x1 + x2 * x2;
}
w = sqrt(-2.0 * log(w) / w);
nn[2 * t] = x1 * w;
nn[2 * t + 1] = x2 * w;
}
if (len_nn % 2 == 1){
w = 2.0;
while (w > 1.0){
x1 = 2.0 * Uniform() - 1.0;
x2 = 2.0 * Uniform() - 1.0;
w = x1 * x1 + x2 * x2;
}
w = sqrt(-2.0 * log(w) / w);
nn[len_nn - 1] = x1 * w;
}
}
计算误码率和误比特率并输出实验结果。
#include"RandNum.h"
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define L 1000
int source_arr[L];
int encode_arr[L];
double total_arr[L];
int decode_arr[L];
/*int* generator() {
int length = 10000000;
int *my_arr = new int[length + 1];
my_arr[0] = length;
int token;
for (int i = 1; i <= length; i++) {
token = rand() % 3 - 1; // generate number between -1~1
my_arr[i] = token > 0 ? 1 : -1;
}
return my_arr;
}
double gaussrand() {
static double V1, V2, S;
static int phase = 0;
double X;
if (phase == 0) {
do {
double U1 = (double)rand() / RAND_MAX;
double U2 = (double)rand() / RAND_MAX;
V1 = 2 * U1 - 1;
V2 = 2 * U2 - 1;
S = V1 * V1 + V2 * V2;
} while (S >= 1 || S == 0);
X = V1 * sqrt(-2 * log(S) / S);
}
else {
X = V2 * sqrt(-2 * log(S) / S);
}
phase = 1 - phase;
return X;
}
double* add_noise(int delta, int length) {
double *my_arr = new double[length + 1];
for (int i = 1; i <= length; i++) {
my_arr[i] = gaussrand();
}
return my_arr;
}
int* BPSK_func(int* int_arr, double* double_arr) {
int length = int_arr[0];
int *return_arr = new int[length + 1];
return_arr[0] = length;
for (int i = 1; i <= length; i++) {
return_arr[i] = abs(double_arr[i] + int_arr[i] - 1) > abs(double_arr[i] + int_arr[i] + 1) ? -1 : 1;
}
return return_arr;
}
int main()
{
int *origin_arr = generator();
double *noise_arr = add_noise(0, origin_arr[0]);
int *BPSK_arr = BPSK_func(origin_arr, noise_arr);
int length = BPSK_arr[0];
int error_num = 0;
for (int i = 1; i <= length; i++) {
if (BPSK_arr[i] != origin_arr[i]) {
error_num++;
}
}
double error_rate = (double)error_num / (double)length;
cout << error_rate << endl;
int i;
cin >> i;
return 0;
}*/
int* generator(int length) {
double token;
CLCRandNum temp;
for (int i = 0; i < length; i++) {
token = temp.Uniform(); // generate number between 0~1
source_arr[i] = token > 0.5 ? 1 : 0;
}
return source_arr;
}
int *encode(int *src_arr, int length) {
for (int i = 0; i < length; i++) {
encode_arr[i] = (src_arr[i] > 0.5) ? 1 : -1;
}
return encode_arr;
}
double *add_noise(int *encode_arr, int length, double delta) {
CLCRandNum temp;
temp.Normal(total_arr, length);
for (int i = 0; i < length; i++) {
total_arr[i] = delta*total_arr[i] + encode_arr[i];
}
return total_arr;
}
int *decode(double *total_arr, int length) {
for (int i = 0; i < length; i++) {
decode_arr[i] = total_arr[i] > 0 ? 1 : 0;
}
return decode_arr;
}
int error_num(int *source_arr, int *decode_arr, int length) {
int error_num = 0;
for (int i = 0; i < length; i++) {
if (source_arr[i] != decode_arr[i]) {
error_num++;
}
}
return error_num;
}
double calculate_delta(double E_No) {
double temp = E_No;
temp = pow(10, temp / 10);
temp = sqrt(0.5 / temp);
return temp;
}
int main() {
double *E_No = new double[100];
double *delta = new double[100];
for (int i = 2; i < 100; i++) {
double temp_int = i;
E_No[i] = double(temp_int / 10);
delta[i] = calculate_delta(E_No[i]);
}
fstream DataWriter;
DataWriter.open("data1.txt", ios::out);
if (!DataWriter) {
cout << "Create File Error" << endl;
exit(0);
}
cout << " Es/No" << " Bit-Error Probability" << endl;
for (int i = 2; i < 100; i++) {
int total_error = 0;
for (int j = 0; j < 10000; j++) {
int *source_arr = generator(L);
int *encode_arr = encode(source_arr, L);
double *total_arr = add_noise(encode_arr, L, delta[i]);
int *decode_arr = decode(total_arr, L);
total_error += error_num(source_arr, decode_arr, L);
}
cout.precision(4);
cout << "X: " << fixed << E_No[i] << ", " << "Y: " << total_error << "*10^(-9)" << endl;
DataWriter << E_No[i] << "," << total_error << "\n";
}
DataWriter.close();
system("pause");
}
实验输出结果: