January 28, 2011
C/C++ create random noise (gaussian noise/white noise)
I was amazed when use randn command at Matlab. randn command will generate random data every we call that command. After I search at google, I found how to make this happen. I get this code at seismic unix source code. This code will generate random noise or white noise with Gaussian method. Code for main.c is :
#include <stdio.h> #include <stdlib.h> #include "frannor.h" int main(int argc, char **argv) { double *noise=NULL; int i; int ndata; unsigned int seed; if(argc!=2) { fprintf(stderr, "usage : random 5"); exit(0); } ndata = atoi(argv[1]); if (-1 == (seed = (unsigned int) time((time_t *) NULL))) { fprintf(stderr, "time() failed to set seed"); exit(0); } srannor(seed); //seed random number generator noise = (double*) calloc (ndata, sizeof(double)); for(i=0; i<ndata; i++) //create random data { /* Compute noise vector elements in [-1, 1] */ /* GAUSS METHOD. frannor gives elements in N(0,1)--ie. pos & negs */ noise[i] = (double) frannor(); } for(i=0; i<ndata; i++) printf("%3.2f ", noise[i]); printf("\n"); free(noise); //free allocated memory return(1); }
This is code for frannor.h :
#ifndef FRANNOR_H_ #define FRANNOR_H_ #include <math.h> #define ABS(x) ((x) < 0 ? -(x) : (x)) #define AA 12.37586 #define Bsu 0.4878992 #define Csu 12.67706 #define C1 0.9689279 #define C2 1.301198 #define PC 0.01958303 #define XN 2.776994 #define OXN 0.3601016 #define NBITS 24 /* macro to generate a random number uni uniform on [0,1) */ #define UNI(uni) \ uni = u[i]-u[j]; if (uni<0.0) uni += 1.0; u[i] = uni; \ if (--i<0) i = 16; if (--j<0) j = 16 float frannor(void); void srannor (int seed); #endif /* FRANNOR_H_ */
This is code for frannor.c :
/* Copyright (c) Colorado School of Mines, 2010.*/ /* All rights reserved. */ /*********************** self documentation **********************/ /***************************************************************************** FRANNOR - functions to generate a pseudo-random float normally distributed with N(0,1); i.e., with zero mean and unit variance. frannor return a normally distributed random float srannor seed random number generator for normal distribution ****************************************************************************** Function Prototypes: float frannor (void); void srannor (int seed); ****************************************************************************** frannor: Input: (none) Returned: normally distributed random float srannor: Input: seed different seeds yield different sequences of random numbers. ****************************************************************************** Notes: Adapted from subroutine rnor in Kahaner, Moler and Nash (1988) which in turn was based on an algorithm by Marsaglia and Tsang (1984). ****************************************************************************** References: "Numerical Methods and Software", D. Kahaner, C. Moler, S. Nash, Prentice Hall, 1988. Marsaglia G. and Tsang, W. W., 1984, A fast, easily implemented method for sampling from decreasing or symmetric unimodal density functions: SIAM J. Sci. Stat. Comput., v. 5, no. 2, p. 349-359. ***************************************************************************** Author: Dave Hale, Colorado School of Mines, 01/21/89 *****************************************************************************/ /**************** end self doc ********************************/ #include "frannor.h" static float v[]={ 0.3409450, 0.4573146, 0.5397793, 0.6062427, 0.6631691, 0.7136975, 0.7596125, 0.8020356, 0.8417227, 0.8792102, 0.9148948, 0.9490791, 0.9820005, 1.0138492, 1.0447810, 1.0749254, 1.1043917, 1.1332738, 1.1616530, 1.1896010, 1.2171815, 1.2444516, 1.2714635, 1.2982650, 1.3249008, 1.3514125, 1.3778399, 1.4042211, 1.4305929, 1.4569915, 1.4834526, 1.5100121, 1.5367061, 1.5635712, 1.5906454, 1.6179680, 1.6455802, 1.6735255, 1.7018503, 1.7306045, 1.7598422, 1.7896223, 1.8200099, 1.8510770, 1.8829044, 1.9155830, 1.9492166, 1.9839239, 2.0198430, 2.0571356, 2.0959930, 2.1366450, 2.1793713, 2.2245175, 2.2725185, 2.3239338, 2.3795007, 2.4402218, 2.5075117, 2.5834658, 2.6713916, 2.7769943, 2.7769943, 2.7769943, 2.7769943 }; /* internal state variables for uniform random number generator */ static int i=16,j=4; static float u[]={ 0.8668672834288, 0.3697986366357, 0.8008968294805, 0.4173889774680, 0.8254561579836, 0.9640965269077, 0.4508667414265, 0.6451309529668, 0.1645456024730, 0.2787901807898, 0.06761531340295, 0.9663226330820, 0.01963343943798, 0.02947398211399, 0.1636231515294, 0.3976343250467, 0.2631008574685 }; float frannor(void) /************************************************************************** return a normally distributed random float *************************************************************************** Returned: normally distributed random float **************************************************************************/ { int k; float uni,vni,rnor,x,y,s,bmbx,xnmx; /* uni is uniform on [0,1) */ UNI(uni); /* vni is uniform on [-1,1) */ vni = uni+uni-1.0; /* k is in range [0,63] */ k = ((int)(u[i]*128))%64; /* fast part */ rnor = vni*v[k+1]; if (ABS(rnor)<=v[k]) return rnor; /* slow part */ x = (ABS(rnor)-v[k])/(v[k+1]-v[k]); UNI(y); s = x+y; if (s<=C2) { if (s<=C1) return rnor; bmbx = Bsu-Bsu*x; if (y<=Csu-AA*exp(-0.5*bmbx*bmbx)) { if (exp(-0.5*v[k+1]*v[k+1])+y*PC/v[k+1] <= exp(-0.5*rnor*rnor)) return rnor; do { UNI(y); x = OXN*log(y); UNI(y); } while (-2.0*log(y)<=x*x); xnmx = XN-x; return (rnor>=0.0 ? ABS(xnmx) : -ABS(xnmx)); } } bmbx = Bsu-Bsu*x; return (rnor>=0.0 ? ABS(bmbx) : -ABS(bmbx)); } void srannor (int seed) /***************************************************************************** seed random number generator ****************************************************************************** Input: seed different seeds yield different sequences of random numbers. *****************************************************************************/ { int ii,jj,ia,ib,ic,id; float s,t; i = 16; j = 4; ia=ABS(seed)%32707; ib=1111; ic=1947; for (ii=0; ii<17; ii++) { s = 0.0; t = 0.5; for (jj=0; jj<64; jj++) { id = ic-ia; if (id<0) { id += 32707; s += t; } ia = ib; ib = ic; ic = id; t *= 0.5; } u[ii] = s; } }
To compile this source code, use command :
gcc main.c frannor.c -lm -o random
This is output from program :
toto@toto-laptop:/home/toto/$ ./random 6 0.08 1.78 -1.35 -1.03 1.62 0.07 toto@toto-laptop:/home/toto/$ ./random 6 1.12 1.32 0.73 -0.34 0.25 -0.58
One Comment