Generating random reals uniformly using Boost [closed] - c++

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 years ago.
Improve this question
I am trying to generate some uniform real numbers for a Monte Carlo integration but the routine I build was returning some really strange values. Upon closer inspection I notices that Boost was returning some crazy looking random numbers e.g.:
temp = -0.185276
temp = -0.864523
temp = -0.0942081
temp = -0.164991
temp = -0.873013
temp = -0.0311322
temp = -0.0866241
temp = -0.778966
temp = -0.367641
temp = -0.691833
temp = 5.66499e-310
temp = 9.42007e-311
temp = 6.29821e-310
temp = 5.80603e-310
temp = 8.82973e-311
temp = 6.73679e-310
temp = 6.35094e-310
temp = 1.53691e-310
temp = 4.39696e-310
temp = 2.14277e-310
Whilst these numbers are technically still reals generated between the bounds -1 and 1 I would prefer it if they weren't quite so small!
My implementation of the call to boost is in a function which is called multiple times (for different bounding values) as follows:
// Define Boost typedefs
typedef boost::mt19937 Engine;
typedef boost::uniform_real<double> Distribution;
typedef boost::variate_generator <Engine, Distribution> Generator;
int main (void) {
...
Integral = MCRecursion(...);
...
return 0;
}
double MCRecursion (int Count, double Lower, double Upper, double (*Integrand)(double)) {
// Define Boost objects
Engine Eng;
Distribution Dist (Lower, Upper);
Generator RandomGen (Eng, Dist);
Eng.seed(time(0));
// Variables for Monte Carlo sample sums
double Sum = 0.0;
double temp;
for (int i = 0; i < Count; i++) {
temp = RandomGen();
std::cout << " temp = " << temp << std::endl;
Sum += Integrand(temp);
}
return (Upper - Lower) * Sum / Count;
}
I assume the problem is something with my implementation but I can't find any errors. Any and all help appreciated!
Cheers,
Jack
EDIT
Code for calling MCRecursion:
The Code I am writting runs a Monte Carlo on the entire domain I am interested in [Lower, Upper] and then looks again at the left half of the whole domain and the right half of the domain.
e.g. if we were integrating f(x) between -a and a I calculate the full integral using:
double FullDomain = MCRecursion (1e5, LowerBound, UpperBound, f);
double Centre = (Upper + Lower) / 2.0;
double LeftHalf = MCRecursion (1e5, LowerBound, Centre, f);
double RightHalf = MCRecursion (1e5, Centre, UpperBound, f);
and I then look at the uncertainty by calculating:
double difference = fabs(FullDomain - LeftHalf - Righthalf);
to see if more samples is 'worth it' in some sense
Jack

Based on the pastebin the questioner posted in the comments:
This is not a problem with the random library but rather a simple programming error. Compiling the code throws the warning:
../src/Test.cpp: In function ‘double AdaptiveMCRecursion(double, double, double, double, int, double, double (*)(double))’:
../src/Test.cpp:100:72: warning: ‘Right’ is used uninitialized in this function [-Wuninitialized]
double Right = MCSample (Count, Central, Right, Integrand);
So all the behaviour from that line on is basically undefined. Especially it results in calling the function MCSample with an undetermined Upper parameter. So your result is not unexpected. You are actually lucky the program runs at all.

Related

Why is my code throwing a SIGBUS error, even when I store variables in heap?

In the method plotThermalNoise() of the Antenna class, for some reason the for loop does not run. Initially, I used int for n and i, however I need to work with much larger numbers than int can hold. SO, now I'm using a long int for both. The program no longer works, however. I stepped through it with GDB, and it seems I'm getting a SIGBUS error. I tried using new so as to store both variables in heap, however the loop still doesn't run.
#define k 0.0000000000000000000000138064852 //Boltzmann's constant
class Antenna{
double _srate, _sdur, _res, _temp, _band;
public:
Antenna(double sampling_rate, double sample_duration, double resistance_ohms, double temperature_kelvin, double bandwidth_Hz){
_srate = sampling_rate; _sdur = sample_duration;
_res = resistance_ohms; _temp = temperature_kelvin;
_band = bandwidth_Hz;
}
void plotThermalNoise();
};
void Antenna::plotThermalNoise(){
//calculate RMS, mean of Gaussian
double RMS = sqrt(4 * _res * k * _temp * _band);
double V = sqrt((4 * k * _temp * _band) / _res);
long int n = _srate / _sdur;
double x[*n],y[*n];
gRandom->SetSeed(time(NULL));
for(long int i = 0; i < n; ++i){
x[i] = i;
y[i] = gRandom->Gaus(V,RMS);
}
TGraph gr = new TGraph(n,x,y);
gr->SetTitle("Thermal Noise Voltage vs Time Trace;Seconds;Volts");
gr->Draw();
}
void dataAquisitionSim(){
Antenna test(4000000000, 0.000001, 50, 90, 500);
test.plotThermalNoise();
}
long int n = _srate / _sdur;
double x[*n],y[*n];
This code will not compile. I assume your actual code is:
long int n = _srate / _sdur;
double x[n],y[n];
With the parameters you pass in: 4000000000 for _srate and 0.000001 for _sdur, n becomes 4,000,000,000 / 0.000,000,1 == 4,000,000,000,000,000.
You then attempt to allocate two double arrays of that size on stack. The total size of these arrays is 64 peta-bytes.
The largest super-computer currently in existence has "over 10PiB of memory". So you only need something mere 6 times larger than that.
it seems I'm getting a SIGBUS error.
As you should. Some back of the envelope calculations should help you realize that just because your code compiles doesn't mean it will run.
even when I store variables in heap?
Unless you actually have a computer with more than 64PiB of RAM, stack vs. heap is irrelevant -- you'll run out of either.

Advice on method to integrate Bessel functions in C++ [duplicate]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
How can I integrate an equation including bessel functions numerically from "0" to "infinity" in Fortran or/and C?
I did in matlab, but it's not true for larger inputs and after a specific values , the bessel functions give completely wrong results(there is a restriction in Matlab)
There's a large number of analytic results for various integrals of the Bessel functions (see DLMF, Sect. 10.22), including definite integrals over precisely this range. You'd be much better off, and almost certainly faster and more accurate, trying hard to recast your expression into something that's integrable and using an exact result.
Last time I had to do with such things, it was state of the art to do simple integration of the intervals defined by the zero crossings. That is in most cases relatively stable and if the integrand is approaching zero reasonable fast easy to do.
As a starting point for playing around I´ve included a bit of code. Of course you need to work on the convergence detection and error checking. This is no production code but I thought maybe it provides a starting point for you. Its using gsl.
On my iMac this code takes about 2 µs per iteration. It will not become faster by including a hardcoded table for the intervals.
I hope this is of some use for you.
#include <iostream>
#include <vector>
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_sf.h>
double f (double x, void * params) {
double y = 1.0 / (1.0 + x) * gsl_sf_bessel_J0 (x);
return y;
}
int main(int argc, const char * argv[]) {
double sum = 0;
double delta = 0.00001;
int max_steps = 1000;
gsl_integration_workspace * w = gsl_integration_workspace_alloc (max_steps);
gsl_function F;
F.function = &f;
F.params = 0;
double result, error;
double a,b;
for(int n=0; n < max_steps; n++)
{
if(n==0)
{
a = 0.0;
b = gsl_sf_bessel_zero_J0(1);
}
else
{
a = n;
b = gsl_sf_bessel_zero_J0(n+1);
}
gsl_integration_qag (&F, // function
besselj0_intervals[n], // from
besselj0_intervals[n+1], // to
0, // eps absolute
1e-4,// eps relative
max_steps,
GSL_INTEG_GAUSS15,
w,
&result,
&error);
sum += result;
std::cout << n << " " << result << " " << sum << "\n";
if(abs(result) < delta)
break;
}
return 0;
}
You can pretty much google and find lots of Bessel functions implemented in C already.
http://www.atnf.csiro.au/computing/software/gipsy/sub/bessel.c
http://jean-pierre.moreau.pagesperso-orange.fr/c_bessel.html
https://msdn.microsoft.com/en-us/library/h7zkk1bz.aspx
In the end, these use the built in types and will be limited to the ranges they can represent (just as MATLAB is). At best, expect 15 digits of precision using double precision floating point representation. So, for large numbers, they will appear to be rounded. eg. 1237846464123450000000000.00000
And, of course, others on Stack Overflow have looked into it.
C++ Bessel function for complex numbers

I was trying to write a Greedy Algorithm in C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Does this make any sense?
I got stuck in here with 4 errors and it is because I didn't declared the ints q,d,n,p. But if I do so it'll keep sending me more errors.
There might be something about having mixed ints and floats.
#include <cs50.h>
#include <stdio.h>
int main(void)
{
{
printf("O hai! ");
}
float valueTotal, quarter, valueQuarter, dime, valueDime,nickel, valueNickel, penny, valuePenny;
do
{
printf("How much change is owed?\n");
valueTotal = GetFloat();
}
while (valueTotal <= 0);
for (float quarter = 0; valueTotal >= 0.25; quarter--)
{
valueQuarter = valueTotal - ( q * 0.25);
}
for (float dime = 0; valueQuarter >= 0.10; dime--)
{
valueDime = valueQuarter - ( d * 0.10);
}
for (float nickel = 0; valueDime >= 0.05; nickel--)
{
valueNickel = valueDime - ( n * 0.05);
}
for (float penny = 0; valueNickel >= 0.01; penny--)
{
valuePenny = valueNickel - ( p * 0.01);
}
printf("q+d+n+p\n");
}
I didn't declared the ints q,d,n,p.
This is exactly your problem - at least one of them, anyways. If these variables are undeclared, how in the world is the program/code supposed to evaluate something like q * 0.25 ? If I said "Hey man, what is x times 0.25?" You'd have absolutely no idea, or tell me that the answer depends on x. The same goes with this code.
You said:
But if I do so it'll keep sending me more errors.
I'm assuming you also need to initialize them (or, in layman's terms, set them equal to something ie. q = 0)
Also, none of your loop conditions are actually changing.... meaning they're infinitely looping. Make sure that the code inside your loop is actually helping you reach the goal of satisfying the loop condition; for example:
for (float quarter = 0; valueTotal >= 0.25; quarter--)
{
valueQuarter = valueTotal - ( q * 0.25);
}
valueTotal is ALWAYS going to be greater than 0.25 (if it is less than 0.25 to begin with) since you are never changing it at all.

Implementing the ratio of uniforms for normal distribution in C++

I understand that this can be done by defining a teardrop shape and accepting points that fall within that region (from a uniform generator).
I am trying to do this in C++ by generating two uniform random numbers x and y to locate the point (x,y), and then checking if this point falls within the region.
I don't have a problem with the code itself, but is there a flaw in my logic here? I haven't found a suitable graphical way to check if this is true normal distribution yet.
Here is the code which is supposed to work:
typedef unsigned long long int Ullong;
typedef double Doub;
struct Normaldev : Ran {
Doub mu,sig;
Normaldev (Doub mmu, Doub ssig, Ullong i)
: Ran (i), mu(mmu), sig(ssig){}
Doub dev() {
Doub u, v, x, y, q;
do {
u=Doub();
v=1.7156*(Doub()-0.5);
x=u-0.449871;
y=abs(v)+0.386595;
q=x*x+y*(0.19600*y-0.25472*x);
} while(q>0.27597 && (q>0.27846 || v*v>-4*log(u)*u*u));
return mu+sig*v/u;
}
};
I changed the suggested code in the Numerical Recipes book as much as I could with my rudimentary knowledge of C++, but what exactly is Ran supposed to be?
I changed the suggested code in the Numerical Recipes book as much as I could with my rudimentary knowledge of C++, but what exactly is Ran supposed to be?
Ran is a parent class of NormalDev. Its not defined in the code you gave. Based on the code it seems to be a pretty generic Random number class that takes an unsigned long long int seed in its constructor.
Have a look at the 3rd Edition of "Numerical Recipes in C", pages 364-369. You'll find out that Box-Muller returns two normally distributed random variables, namely 'u' and 'v'. So the first time the function is called, you calculate both variables but return just 'u'. The second call of the function does nothing but returning 'v'.
double u, v;
double sigma = 1.0
double mean = 0.0;
int flag = 0;
double boxMuller()
{
if (flag == 1) {
flag = 0;
return v * sigma + mean;
}
double help;
do {
u = Doub() - 0.5;
v = Doub() - 0.5;
help = u * u + v * v;
} while (help >= 0.25);
help = sqrt( log( help * 4.0 ) / help * -2.0 );
u *= help;
v *= help;
flag = 1;
return u * sigma + mean;
}
The Ratio-of-Uniforms method in contrast has to calculate a new random variable on every call (not every second).
So i measured the times, and prefer using the Box-Muller code above.

float value issue

I am facing problem using float
in loop its value stuck at 8388608.00
int count=0;
long X=10;
cout.precision(flt::digits10);
cout<<"Iterration #"<<setw(15)<<"Add"<<setw(21)<<"Mult"<<endl;
float Start=0.0;
float Multiplication = Addition * N;
long i = 1;
for (i; i <= N; i++){
float temp = Start + Addition;
Start=temp;
count++;
if(count%X==0 && count!=0)
{
X*=10;
cout<<i;
cout<<fixed<<setw(30)<<Start<<setw(20)<<fixed<<i*Addition<<endl;
}
}
what should i do??
Floating point addition doesn't work when you're adding (relatively) small number to (relatively) big one. It's caused by the way float is stored in memory.
You may try replacing single precision floating point (float) with double precision floating point (double) representation but if that doesn't work you'll probably need to implement hack like this:
// Lets say
double OriginalAddition = 0.123;
int Addition = 1;
// You just use base math substitution:
// Addition = OriginalAddition
int temp = Start + Addition; // You will treat transform floating point to fixed point
// with step 0.123, so 1 = 0.123
// And when displaying result (transform back into original floating point):
printf( "%f", (double)result*OriginalAddition)
This needs a lot of thought to find a substitution that doesn't cause data loss, covers required precision and won't cause int to overflow. Try to google fixed point int C (some results: 1, 2) to get better idea what to do.