views:

701

answers:

8
A: 

Well, there's good old Wikipedia, of course. And Mathworld.

What you want is a random number generator for "generating normally distributed random deviates". Since Objective C can call regular C libraries, you either need a C-callable library like the GNU Scientific Library, or for this, you can write it yourself following the description here.

Charlie Martin
So my confusion is with the fact that... i'm not looking for a random number.... i want to know if x = 5 then y should be 5... if x is 10 then y should be 0 ... and all those other not so easy in between ones :)
dizy
+2  A: 

The thing you want to plot is the probability density function (pdf) of the normal distribution. You can find it on the mighty Wikipedia.

Luckily, the pdf for a normal distribution is not difficult to implement - some of the other related functions are considerably worse because they require the error function.

To get a plot like you showed, you want a mean of 5 and a standard deviation of about 1.5. The median is obviously the centre, and figuring out an appropriate standard deviation given the left & right boundaries isn't particularly difficult.

A function to calculate the y value of the pdf given the x coordinate, standard deviation and mean might look something like:

double normal_pdf(double x, double mean, double std_dev) {
    return( 1.0/(sqrt(2*PI)*std_dev) *
            exp(-(x-mean)*(x-mean)/(2*std_dev*std_dev)) );
}
Peter
1.5 for the std_dev isn't exactly giving me 5, and you said figuring it out shouldn't be particularly difficult, but I can't seem to figure it out :)
dizy
A: 

Try simulating rolls of dice by generating random numbers between 1 and 6. If you add up the rolls from 5 independent dice rolls, you'll get a surprisingly good approximation to the normal distribution. You can roll more dice if you'd like and you'll get a better approximation.

Here's an article that explains why this works. It's probably more mathematical detail than you want, but you could show it to someone to justify your approach.

John D. Cook
+2  A: 

A normal distribution is never equal to 0. Please make sure that what you want to plot is indeed a normal distribution.

If you're only looking for this bell shape (with the tangent and everything) you can use the following formula:

x^2*(x-10)^2 for x between 0 and 10
                0 elsewhere

(Divide by 125 if you need to have your peek on 5.)

double bell(double x) {
    if ((x < 10) && (x>0))
        return x*x*(x-10.)*(x-10.)/125.;
    else
        return 0.;
}
poulejapon
I have no clue if what I really need is actually a normal distribution, so if you avoid what I called it and just go by my description.... what would it be called?
dizy
seems like the answer has to be devided by 25 to get it to peek at 5
dizy
Sorry I corrected, by the way isn't it 125?Could you explain why you need such a function so that we can tell you whether you need a normal psf or not?
poulejapon
"if you avoid what I called it and just go by my description.... what would it be called?" You described a pretty generic function of one variable; hard to know if it's a PDF or not. Can you edit the question with what you need it *for*/want to *do* with it?
kquinn
edited the question
dizy
Thank you for editing the question. My answer is correct for your purpose and is very fast to compute.
poulejapon
A: 

If what you want is the value of the probability density function, p(x), of a normal (Gaussian) distribution of mean mu and standard deviation sigma at x, the formula is

p(x) = exp( ((x-mu)^2)/(2*sigma^2) ) / (sigma * 2 * sqrt(pi))

where pi is the area of a circle divided by the square of its radius (approximately 3.14159...). Using the C standard library math.h, this is:

#include <math>

double normal_pdf(double x, double mu, double sigma) {
  double n = sigma * 2 * sqrt(M_PI); //normalization factor
  p = exp( -pow(x-mu, 2) / (2 * pow(sigma, 2)) ); // unnormalized pdf

  return p / n;
}

Of course, you can do the same in Objective-C.

For reference, see the Wikipedia or MathWorld articles.

Barry Wark
A: 

It sounds like you want to write a function that yields a curve of a specific shape. Something like y = f(x), for x in [0:10]. You have a constraint on the max value of y, and a general idea of what you want the curve to look like (somewhat bell-shaped, y=0 at the edges of the x range, y=5 when x=5). So roughly, you would call your function iteratively with the x range, with a step that gives you enough points to make your curve look nice.

So you really don't need random numbers, and this has nothing to do with probability unless you want it to (as in, you want your curve to look like a the outline of a normal distribution or something along those lines).

If you have a clear idea of what function will yield your desired curve, the code is trivial - a function to compute f(x) and a for loop to call it the desired number of times for the desired values of x. Plot the x,y pairs and you're done. So that's your algorithm - call a function in a for loop.

The contents of the routine implementing the function will depend on the specifics of what you want the curve to look like. If you need help on functions that might return a curve resembling your sample, I would direct you to the reading material in the other answers. :) However, I suspect that this is actually an assignment of some sort, and that you have been given a function already. If you are actually doing this on your own to learn, then I again echo the other reading suggestions.

John Grieggs
+1  A: 

Okay, your edit really clarifies things. You're not looking for anything to do with the normal distribution, just a nice smooth little ramp function. The one Paul provides will do nicely, but is tricky to modify for other values. It can be made a little more flexible (my code examples are in Python, which should be very easy to translate to any other language):

def quarticRamp(x, b=10, peak=5):
    if not 0 <= x <= b:
        raise ValueError   #or return 0
    return peak*x*x*(x-b)*(x-b)*16/(b*b*b*b)

Parameter b is the upper bound for the region you want to have a slope on (10, in your example), and peak is how high you want it to go (5, in the example).

Personally I like a quadratic spline approach, which is marginally cheaper computationally and has a different curve to it (this curve is really nice to use in a couple of special applications that don't happen to matter at all for you):

def quadraticSplineRamp(x, a=0, b=10, peak=5):
    if not a <= x <= b:
        raise ValueError   #or return 0
    if x > (b+a)/2:
        x = a + b - x
    z = 2*(x-a)/b
    if z > 0.5:
        return peak * (1 - 2*(z-1)*(z-1))
    else:
        return peak * (2*z*z)

This is similar to the other function, but takes a lower bound a (0 in your example). The logic is a little more complex because it's a somewhat-optimized implementation of a piecewise function.

The two curves have slightly different shapes; you probably don't care what the exact shape is, and so could pick either. There are an infinite number of ramp functions meeting your criteria; these are two simple ones, but they can get as baroque as you want.

kquinn
exactly what I was looking for, thanks!
dizy
A: 

y=-1*abs(x-5)+5

Pyetras