Implementing Box-Mueller random number generator in C# - c#

From this question: Random number generator which gravitates numbers to any given number in range? I did some research since I've come across such a random number generator before. All I remember was the name "Mueller", so I guess I found it, here:
Box-Mueller transform
I can find numerous implementations of it in other languages, but I can't seem to implement it correctly in C#.
This page, for instance, The Box-Muller Method for Generating Gaussian Random Numbers says that the code should look like this (this is not C#):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
double gaussian(void)
{
static double v, fac;
static int phase = 0;
double S, Z, U1, U2, u;
if (phase)
Z = v * fac;
else
{
do
{
U1 = (double)rand() / RAND_MAX;
U2 = (double)rand() / RAND_MAX;
u = 2. * U1 - 1.;
v = 2. * U2 - 1.;
S = u * u + v * v;
} while (S >= 1);
fac = sqrt (-2. * log(S) / S);
Z = u * fac;
}
phase = 1 - phase;
return Z;
}
Now, here's my implementation of the above in C#. Note that the transform produces 2 numbers, hence the trick with the "phase" above. I simply discard the second value and return the first.
public static double NextGaussianDouble(this Random r)
{
double u, v, S;
do
{
u = 2.0 * r.NextDouble() - 1.0;
v = 2.0 * r.NextDouble() - 1.0;
S = u * u + v * v;
}
while (S >= 1.0);
double fac = Math.Sqrt(-2.0 * Math.Log(S) / S);
return u * fac;
}
My question is with the following specific scenario, where my code doesn't return a value in the range of 0-1, and I can't understand how the original code can either.
u = 0.5, v = 0.1
S becomes 0.5*0.5 + 0.1*0.1 = 0.26
fac becomes ~3.22
the return value is thus ~0.5 * 3.22 or ~1.6
That's not within 0 .. 1.
What am I doing wrong/not understanding?
If I modify my code so that instead of multiplying fac with u, I multiply by S, I get a value that ranges from 0 to 1, but it has the wrong distribution (seems to have a maximum distribution around 0.7-0.8 and then tapers off in both directions.)

Your code is fine. Your mistake is thinking that it should return values exclusively within [0, 1]. The (standard) normal distribution is a distribution with nonzero weight on the entire real line. That is, values outside of [0, 1] are possible. In fact, values within [-1, 0] are just as likely as values within [0, 1], and moreover, the complement of [0, 1] has about 66% of the weight of the normal distribution. Therefore, 66% of the time we expect a value outside of [0, 1].
Also, I think this is not the Box-Mueller transform, but is actually the Marsaglia polar method.

I am no mathematician, or statistician, but if I think about this I would not expect a Gaussian distribution to return numbers in an exact range. Given your implementation the mean is 0 and the standard deviation is 1 so I would expect values distributed on the bell curve with 0 at the center and then reducing as the numbers deviate from 0 on either side. So the sequence would definitely cover both +/- numbers.
Then since it is statistical, why would it be hard limited to -1..1 just because the std.dev is 1? There can statistically be some play on either side and still fulfill the statistical requirement.

The uniform random variate is indeed within 0..1, but the gaussian random variate (which is what Box-Muller algorithm generates) can be anywhere on the real line. See wiki/NormalDistribution for details.

I think the function returns polar coordinates. So you need both values to get correct results.
Also, Gaussian distribution is not between 0 .. 1. It can easily end up as 1000, but probability of such occurrence is extremely low.

This is a monte carlo method so you can't clamp the result, but what you can do is ignore samples.
// return random value in the range [0,1].
double gaussian_random()
{
double sigma = 1.0/8.0; // or whatever works.
while ( 1 ) {
double z = gaussian() * sigma + 0.5;
if (z >= 0.0 && z <= 1.0)
return z;
}
}

Related

C# MathNet FFT Definition

I have some problem when testing FFT from MathNet:
The idea is that if I apply FFT to the characteristic function of a gaussian variable I should find the gaussian density function.
When I plot VectorFFT the figure does seems a density function but in zero it does not have value 1, it has value 1.4689690914109.
There must be some problems with the scaling. I tried out all type of FourierOptions in Fourier.Inverse and all type of divisions/multiplications for PI, 2PI, sqrt(2PI) but nothing gives me the value 1 at the center of the density function.
Also, since various definitions of Fourier Transform and its inverse exists, I was wondering which one is implemented by MathNet, I could not find it in the documentation.
Any ideas?
public void DensityGaussian()
{
double eta = 0.1; //step in discrete integral
int pow2 = 256; // N^2
double mu = 0; // centred gaussian
double sigma = 1; // with unitary variance
//FFT
double lambda = 2 * System.Math.PI / (pow2 * eta);
double b = 0.5 * pow2 * lambda;
Complex[] VectorToFFT = new Complex[pow2];
for (int j = 0; j < pow2; j++)
{
double z = eta * j;
if (z == 0) { z = 0.00000000000001; }
VectorToFFT[j] = System.Numerics.Complex.Exp(new Complex(0, b * z));
VectorToFFT[j] *= (System.Numerics.Complex.Exp(new Complex(
-sigma*sigma*z*z, mu * z))); //char function of gaussian
}
Fourier.Inverse(VectorToFFT, FourierOptions.NoScaling);
//scaling
for (int i = 0; i < pow2; i++)
{
VectorToFFT[i] /= (2 * System.Math.PI); //test
}
Console.WriteLine("Is density?");
Assert.IsTrue(1 == 1);
}
Math.NET Numerics supports all common DFT definitions, controllable with the FourierOptions flags enum. They essentially vary on the exponent and on the scaling.
The FourierOptions docs give some hints on how the options affect the effective definition, essentially:
InverseExponent: use a negative sign in the exponent (default uses a positive sign). A prominent implementation with a negative sign is numerical recipes.
AsymmetricScaling/NoScaling: instead of the default symmetric scaling sqrt(1/N) either only scale in the inverse transformation 1/N (like Matlab) or no scaling at all (like numerical recipes). Obviously, without scaling ifft(fft(x)) != x.
Maybe the answer in Calculating a density from the characteristic function using fft in R can help on the specific use case.

BesselK Function in C#

I am attempting to implement the BesselK method from Boost (a C++ library).
The Boost method accepts two doubles and returns a double. (I have it implemented below as cyl_bessel_k .)
The equation I modeled this off of comes from Boosts documention:
http://www.boost.org/doc/libs/1_45_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/bessel/mbessel.html
I have also been checking values against Wolfram:
http://www.wolframalpha.com/input/?i=BesselK%283%2C1%29
I am able to match output from the Boost method when passing a positive non-integer value for "v". However, when an integer is passed, my output is severely off. So,there is an obvious discontinuity issue. From reading up on this, it seems that this issue arises from passing a negative integer to the gamma function. Somehow reflection comes into play here with the Bessel_I method, but I'm nearing the end of my math skillset.
1.) What needs to happen to the bessel_i method with reflection to make this work?
2.) I'm currently doing a partial sum approach. Boost uses a continuous fraction approach. How can I modify this to account for convergence?
Any input is appreciated! Thank you!
static double cyl_bessel_k(double v, double x)
{
if (v > 0)
{
double iNegativeV = cyl_bessel_i(-v, x);
double iPositiveV = cyl_bessel_i(v, x);
double besselSecondKind = (Math.PI / 2) * ((iNegativeV - iPositiveV ) / (Math.Sin(Math.PI * v)));
return besselSecondKind;
}
else
{
//error handling
}
}
static double cyl_bessel_i(double v, double x)
{
if (x == 0)
{
return 0;
}
double summed = 0;
double a = Math.Pow((0.5d * x), v);
for (double k = 0; k < 10; k++) //how to account for convergence? 10 is arbitrary
{
double b = Math.Pow(0.25d * Math.Pow(x, 2), k);
double kFactorial = SpecialFunctions.Factorial((int)k); //comes from MathNet.Numerics (Nuget)
double gamma = SpecialFunctions.Gamma(v + k + 1); //comes from MathNet.Numerics
summed += b / (kFactorial * gamma);
}
return a * summed;
}
After lots of refactoring and trying things that didn't work, this is what I came up with. It's mostly Boost logic that has been adapted and translated into C#.
It's not perfect though (likely due to rounding, precision,etc). Any improvements are welcome! Max error is 0.0000001926% between true Bessel_K value from Wolfram and my adapted method. This is occurs when parameter 'v' is an integer. For my purposes, this was close enough.
Link to fiddle:
https://dotnetfiddle.net/QIYzK6
Hopefully it saves someone some headache.

Interpolating Z values when given complete and incomplete XYZ pairs

I am building a windows form application that works with PolyLineZ (ESRI Shapefile) data and rewrites outlying Z values. The minimum and maximum Z-values are defined by the user through the interface
Let's take the following as an example, let's say the minimum is 0 and the maximum is 10:
XY Z
1,1 0
1,3 1
1,5 7
1,7 11*
1,10 10
The value with the 11 would need to be interpolated as it does not fall into the range defined by the user. This is a very simplified example obviously. Some PolyLines can be missing more values.
What I've done:
I've researched linear interpolation. Looked at example youtube videos, having a hard time wrapping my head around it.
What I need:
Code examples from either any language or an "English" explanation of the theory behind linear/bilinear/trilinear interpolation so that I can implement it into my program. My math skills aren't the greatest, so I have a hard time understanding wikipedias definition of it.
I'm also assuming that linear interpolation is what I need to research,
EDIT: Currently implementing the following, stop me if I'm wrong
I'm using what I think is Pythagorean Theory type approach. I haven't made it catch exceptions yet (ie, making sure the left point is actually left, make sure the list doesn't run out of bounds, etc), that can come later
internal static double calculateDistance(XYPoints a, XYPoints b)
{
double xd = b.X - a.X;
double yd = b.Y - a.Y;
return Math.Sqrt(xd * xd + yd * yd);
}
for (var i = 0; i < polylinez.ZPoints.Count;i++)
{
if (polylinez.ZPoints[i] > maxValue || (polylinez.ZPoints[i] < minValue))
{
//polylinez.ZPoints[i] = (((1 - polylinez.XYpoints[i].X) * polylinez.ZPoints[i - 1]) + (polylinez.XYpoints[i].X * polylinez.ZPoints[i + 1]));
double prevdistance = calculateDistance(polylinez.XYpoints[i - 1], polylinez.XYpoints[i]);
double nextdistance = calculateDistance(polylinez.XYpoints[i], polylinez.XYpoints[i + 1]);
double fraction = prevdistance / nextdistance;
double diffsBetweensZ = polylinez.ZPoints[i + 1] - polylinez.ZPoints[i - 1];
Console.WriteLine(polylinez.ZPoints[i - 1] + (diffsBetweensZ * fraction));
}
}
return polylinez;
It returns 9.12 as an answer for the above example table. This sounds about right to me. I checked my distance calculator method with sample data on the internet, and it seems to be doing the trick.
First step, create a routine for calculating distances:
internal static double calculateDistance(XYPoints a, XYPoints b)
{
double xd = b.X - a.X;
double yd = b.Y - a.Y;
return Math.Sqrt(xd * xd + yd * yd);
}
I changed the variable names to something more logical (my variable names were different)
//get distance frpm previous point to point in question
double prevdistance = calculateDistance(prevXYpoint, currentXYPoint);
//get distance frpm point in question to the next point
double nextdistance = calculateDistance(currentXYPoint, nextXYPoint);
//generate a ratio
double fraction = prevdistance / (nextdistance + prevdistance);
//find out the difference between the two known points
double diffsBetweensZ = nextZpointValue - prevZpointValue;
//interpolate!
double newZvalue = (prevZpointValue + (diffsBetweensZ * fraction));
I checked this on several sets of data and it's the most accurate thing I can find... what blows my mind is that I couldn't find any existing code anywhere to do this.

How to create a slider with a non-linear scale?

I have a slider with a minimum value of 0 and maximum of 500.
I want to when the slider goes to 100, the thumb be in the middle of the slider.
I know it seems wierd, but some programs do it with zoom slider, and I believe it's better.
A good formula for the displayed value is a monotonous function such as a power curve, in the following form:
DisplayValue = A + B * Math.Exp(C * SliderValue);
The internal slider value (from 0 to 1 for instance) is obtained by inverting the formula:
SliderValue = Math.Log((DisplayValue - A) / B) / C;
Now how to obtain A, B and C? By using the three constraints you gave:
f(0.0) = 0
f(0.5) = 100
f(1.0) = 500
Three equations, three unknowns, this is solved using basic maths:
A + B = 0
A + B exp(C * 0.5) = 100
A + B exp(C) = 500
B (exp(C * 0.5) - 1) = 100
B (exp(C) - 1) = 500
exp(C) - 5 exp(C * 0.5) + 4 = 0 // this is a quadratic equation
exp(C * 0.5) = 4
C = log(16)
B = 100/3
A = -100/3
Yielding the following code:
double B = 100.0 / 3;
double C = Math.Log(16.0);
DisplayValue = B * (Math.Exp(C * SliderValue) - 1.0);
You can see that the display value is at 100 when the internal value is in the middle:
Edit: since a generic formula was requested, here it is. Given:
f(0.0) = x
f(0.5) = y
f(1.0) = z
The values for A, B and C are:
A = (xz - y²) / (x - 2y + z)
B = (y - x)² / (x - 2y + z)
C = 2 * log((z-y) / (y-x))
Note that if x - 2y + z or y - x is zero, there is no solution and you’ll get a division by zero. That’s because in this case, the scale is actually linear. You need to take care of that special case.
let the slider as it is and use a ValueConverter for your bindings. In the ValueConverter use the non-linear scaling to scale the value as you wish.
Just as a further reference; if you are not interested on exact positions for your slider to correspond to specific values in your scale but still want a behavior where the slider is more sensitive to values on the beginning of the scale than on the end, then perhaps using a simple log scale may suffice.
public class LogScaleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double x = (int)value;
return Math.Log(x);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
double x = (double)value;
return (int)Math.Exp(x);
}
}
Based on the algorithm from sam hocevar, here is the code I put together :
/// <summary>
/// Scale a linear range between 0.0-1.0 to an exponential scale using the equation returnValue = A + B * Math.Exp(C * inputValue);
/// </summary>
/// <param name="inoutValue">The value to scale</param>
/// <param name="midValue">The value returned for input value of 0.5</param>
/// <param name="maxValue">The value to be returned for input value of 1.0</param>
/// <returns></returns>
private double ExpScale(double inputValue, double midValue, double maxValue)
{
double returnValue = 0;
if (inputValue < 0 || inputValue > 1) throw new ArgumentOutOfRangeException("Input value must be between 0 and 1.0");
if (midValue <= 0 || midValue >= maxValue) throw new ArgumentOutOfRangeException("MidValue must be greater than 0 and less than MaxValue");
// returnValue = A + B * Math.Exp(C * inputValue);
double M = maxValue / midValue;
double C = Math.Log(Math.Pow(M - 1, 2));
double B = maxValue / (Math.Exp(C) - 1);
double A = -1 * B;
returnValue = A + B * Math.Exp(C * inputValue);
return returnValue;
}
This was such an interesting question that I couldn't leave it alone, and hopefully I got what you're asking right :)
You want to change the Value of a Slider from Linear to a Quadratic Function by specifying the Y value of the function when the Thumb is in the middle.
A Quadratic Function is written on the form
Since we have 3 points, we have 3 sets of values for X and Y.
(X1, Y1) = 0, 0
(X2, Y2) = MiddleX, CenterQuadraticValue (in your case 100)
(X3, Y3) = Maximum, Maximum (in your case 500)
From here, we can create a Quadratic Equation (see this link for example) which comes out to
Unfortunately, some values in this graph ends up below 0 so they will have to be coerced to 0 (I included a graph in the bottom of the answer).
I created a control, QuadraticSlider, which derives from Slider and adds two Dependency Properties: QuadraticValue and CenterQuadraticValue. It calculates QuadraticValue using the formula above based on Value, Maximum, Minimum and CenterQuadraticValue. It also does the reverse: setting QuadraticValue updates Value. So instead of Binding to Value, bind to QuadraticValue.
Edit: The last version was a little buggy. Fixed a couple of things
Calculating Value from QuadraticValue no longer breaks when "a" is 0
Used wrong root from the second degree solution when the derivate was negative
I uploaded a sample application where QuadraticSlider is used to zoom a picture. All parameteres can be specified and the first picture uses Value and the other QuadraticValue.
Download it here if you want to try it out.
It looks like this
And this is what the graph looks like, notice the values below 0
Some addition to Meleak's post.
I've slightly corrected QuadraticSlider. There was issue with event handlers (event on QuadraticValueChanged with yet prevoius value; event during initialization with out of range [min, max] value).
protected override void OnValueChanged(double oldValue, double newValue)
{
QuadraticValue = a * Math.Pow(Value, 2) + b * Value + c;
base.OnValueChanged(oldValue, newValue);
}
public double QuadraticValue
{
get {
var qv = (double)GetValue(QuadraticValueProperty);
if (double.IsNaN(qv))
qv = 0;
qv = Math.Max(qv, base.Minimum);
qv = Math.Min(qv, base.Maximum);
return qv;
}
set
{
SetValue(QuadraticValueProperty, value);
}
}
To generalise on Sam Hocevar's excellent answer:
Let the intended Maximum value be M.
Let the value at the slider midpoint be m.
(obviously, 0 < m < M), then
A = - M*m^2 / (M^2 - 2*m*M)
B = M*m^2 / (M^2 - 2*m*M)
C = Ln((M - m)^2 / m^2) // <- logarithm to the base of e, I always think of 'Log' as base 10
One must take care to treat the case 2*m=M seperately, because that leads to a division by 0. But in that case, you'd have the slider behave in a linear fashion anyway.
Chosing m from between M/2 and M makes for a logarithmic curve: The effective slider values rise fast at first, then slowly later on. This basically reverses the effect and gives the user finer control of the higher values.
As mentioned, an m close to M/2 makes the slider basically linear.
Choosing m close to 0 or close to M makes for fine control over the very low or the very high values.
I suppose one could use this in combination with a second slider that sets m to a value between 0 and M to change the ... errr ... sensitive zone of the real slider.
Not nearly as elegant as some of the other answers here but instead of a smooth curve you could just use two straight lines. With y as your slider's position and x as your actual value, you'd use (y1 - y2)/(x1 - x2) to get the slope, then y - y1 = slope * (x - x1) to get the y intercept. Do that for each half of the slider then use a conditional statement to treat values differently depending on whether they are above or below 50. The basic maths in your case:
(0 - 50)/(0 - 100)
-50/-100
1/2
y = x/2
...since we know the y intercept is 0. Then...
(50-100)/(100-500)
-50/-400
1/8
y - 50 = 1/8 * (x - 100)
y - 50 = x/8 - 25/2
y = x/8 + 75/2
From a user experience perspective, you're definitely better off using a curve (I especially like Cesar's log idea) because it avoids a sharp "elbow" where the slider starts suddenly increasing values at a totally different rate. But this approach is simple to implement and flexible (you could easily add more zones with different ratios) so I thought it was worth mentioning it anyway.
Here is the go code for deriving the exponential equation: https://play.golang.org/p/JlWlwZjoebE

How do I calculate PI in C#?

How can I calculate the value of PI using C#?
I was thinking it would be through a recursive function, if so, what would it look like and are there any math equations to back it up?
I'm not too fussy about performance, mainly how to go about it from a learning point of view.
If you want recursion:
PI = 2 * (1 + 1/3 * (1 + 2/5 * (1 + 3/7 * (...))))
This would become, after some rewriting:
PI = 2 * F(1);
with F(i):
double F (int i) {
return 1 + i / (2.0 * i + 1) * F(i + 1);
}
Isaac Newton (you may have heard of him before ;) ) came up with this trick.
Note that I left out the end condition, to keep it simple. In real life, you kind of need one.
How about using:
double pi = Math.PI;
If you want better precision than that, you will need to use an algorithmic system and the Decimal type.
If you take a close look into this really good guide:
Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4
You'll find at Page 70 this cute implementation (with minor changes from my side):
static decimal ParallelPartitionerPi(int steps)
{
decimal sum = 0.0;
decimal step = 1.0 / (decimal)steps;
object obj = new object();
Parallel.ForEach(
Partitioner.Create(0, steps),
() => 0.0,
(range, state, partial) =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
decimal x = (i - 0.5) * step;
partial += 4.0 / (1.0 + x * x);
}
return partial;
},
partial => { lock (obj) sum += partial; });
return step * sum;
}
There are a couple of really, really old tricks I'm surprised to not see here.
atan(1) == PI/4, so an old chestnut when a trustworthy arc-tangent function is
present is 4*atan(1).
A very cute, fixed-ratio estimate that makes the old Western 22/7 look like dirt
is 355/113, which is good to several decimal places (at least three or four, I think).
In some cases, this is even good enough for integer arithmetic: multiply by 355 then divide by 113.
355/113 is also easy to commit to memory (for some people anyway): count one, one, three, three, five, five and remember that you're naming the digits in the denominator and numerator (if you forget which triplet goes on top, a microsecond's thought is usually going to straighten it out).
Note that 22/7 gives you: 3.14285714, which is wrong at the thousandths.
355/113 gives you 3.14159292 which isn't wrong until the ten-millionths.
Acc. to /usr/include/math.h on my box, M_PI is #define'd as:
3.14159265358979323846
which is probably good out as far as it goes.
The lesson you get from estimating PI is that there are lots of ways of doing it,
none will ever be perfect, and you have to sort them out by intended use.
355/113 is an old Chinese estimate, and I believe it pre-dates 22/7 by many years. It was taught me by a physics professor when I was an undergrad.
Good overview of different algorithms:
Computing pi;
Gauss-Legendre-Salamin.
I'm not sure about the complexity claimed for the Gauss-Legendre-Salamin algorithm in the first link (I'd say O(N log^2(N) log(log(N)))).
I do encourage you to try it, though, the convergence is really fast.
Also, I'm not really sure about why trying to convert a quite simple procedural algorithm into a recursive one?
Note that if you are interested in performance, then working at a bounded precision (typically, requiring a 'double', 'float',... output) does not really make sense, as the obvious answer in such a case is just to hardcode the value.
What is PI? The circumference of a circle divided by its diameter.
In computer graphics you can plot/draw a circle with its centre at 0,0 from a initial point x,y, the next point x',y' can be found using a simple formula:
x' = x + y / h : y' = y - x' / h
h is usually a power of 2 so that the divide can be done easily with a shift (or subtracting from the exponent on a double). h also wants to be the radius r of your circle. An easy start point would be x = r, y = 0, and then to count c the number of steps until x <= 0 to plot a quater of a circle. PI is 4 * c / r or PI is 4 * c / h
Recursion to any great depth, is usually impractical for a commercial program, but tail recursion allows an algorithm to be expressed recursively, while implemented as a loop. Recursive search algorithms can sometimes be implemented using a queue rather than the process's stack, the search has to backtrack from a deadend and take another path - these backtrack points can be put in a queue, and multiple processes can un-queue the points and try other paths.
Calculate like this:
x = 1 - 1/3 + 1/5 - 1/7 + 1/9 (... etc as far as possible.)
PI = x * 4
You have got Pi !!!
This is the simplest method I know of.
The value of PI slowly converges to the actual value of Pi (3.141592165......). If you iterate more times, the better.
Here's a nice approach (from the main Wikipedia entry on pi); it converges much faster than the simple formula discussed above, and is quite amenable to a recursive solution if your intent is to pursue recursion as a learning exercise. (Assuming that you're after the learning experience, I'm not giving any actual code.)
The underlying formula is the same as above, but this approach averages the partial sums to accelerate the convergence.
Define a two parameter function, pie(h, w), such that:
pie(0,1) = 4/1
pie(0,2) = 4/1 - 4/3
pie(0,3) = 4/1 - 4/3 + 4/5
pie(0,4) = 4/1 - 4/3 + 4/5 - 4/7
... and so on
So your first opportunity to explore recursion is to code that "horizontal" computation as the "width" parameter increases (for "height" of zero).
Then add the second dimension with this formula:
pie(h, w) = (pie(h-1,w) + pie(h-1,w+1)) / 2
which is used, of course, only for values of h greater than zero.
The nice thing about this algorithm is that you can easily mock it up with a spreadsheet to check your code as you explore the results produced by progressively larger parameters. By the time you compute pie(10,10), you'll have an approximate value for pi that's good enough for most engineering purposes.
Enumerable.Range(0, 100000000).Aggregate(0d, (tot, next) => tot += Math.Pow(-1d, next)/(2*next + 1)*4)
using System;
namespace Strings
{
class Program
{
static void Main(string[] args)
{
/* decimal pie = 1;
decimal e = -1;
*/
var stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start(); //added this nice stopwatch start routine
//leibniz formula in C# - code written completely by Todd Mandell 2014
/*
for (decimal f = (e += 2); f < 1000001; f++)
{
e += 2;
pie -= 1 / e;
e += 2;
pie += 1 / e;
Console.WriteLine(pie * 4);
}
decimal finalDisplayString = (pie * 4);
Console.WriteLine("pie = {0}", finalDisplayString);
Console.WriteLine("Accuracy resulting from approximately {0} steps", e/4);
*/
// Nilakantha formula - code written completely by Todd Mandell 2014
// π = 3 + 4/(2*3*4) - 4/(4*5*6) + 4/(6*7*8) - 4/(8*9*10) + 4/(10*11*12) - (4/(12*13*14) etc
decimal pie = 0;
decimal a = 2;
decimal b = 3;
decimal c = 4;
decimal e = 1;
for (decimal f = (e += 1); f < 100000; f++)
// Increase f where "f < 100000" to increase number of steps
{
pie += 4 / (a * b * c);
a += 2;
b += 2;
c += 2;
pie -= 4 / (a * b * c);
a += 2;
b += 2;
c += 2;
e += 1;
}
decimal finalDisplayString = (pie + 3);
Console.WriteLine("pie = {0}", finalDisplayString);
Console.WriteLine("Accuracy resulting from {0} steps", e);
stopwatch.Stop();
TimeSpan ts = stopwatch.Elapsed;
Console.WriteLine("Calc Time {0}", ts);
Console.ReadLine();
}
}
}
public static string PiNumberFinder(int digitNumber)
{
string piNumber = "3,";
int dividedBy = 11080585;
int divisor = 78256779;
int result;
for (int i = 0; i < digitNumber; i++)
{
if (dividedBy < divisor)
dividedBy *= 10;
result = dividedBy / divisor;
string resultString = result.ToString();
piNumber += resultString;
dividedBy = dividedBy - divisor * result;
}
return piNumber;
}
In any production scenario, I would compel you to look up the value, to the desired number of decimal points, and store it as a 'const' somewhere your classes can get to it.
(unless you're writing scientific 'Pi' specific software...)
Regarding...
... how to go about it from a learning point of view.
Are you trying to learning to program scientific methods? or to produce production software? I hope the community sees this as a valid question and not a nitpick.
In either case, I think writing your own Pi is a solved problem. Dmitry showed the 'Math.PI' constant already. Attack another problem in the same space! Go for generic Newton approximations or something slick.
#Thomas Kammeyer:
Note that Atan(1.0) is quite often hardcoded, so 4*Atan(1.0) is not really an 'algorithm' if you're calling a library Atan function (an quite a few already suggested indeed proceed by replacing Atan(x) by a series (or infinite product) for it, then evaluating it at x=1.
Also, there are very few cases where you'd need pi at more precision than a few tens of bits (which can be easily hardcoded!). I've worked on applications in mathematics where, to compute some (quite complicated) mathematical objects (which were polynomial with integer coefficients), I had to do arithmetic on real and complex numbers (including computing pi) with a precision of up to a few million bits... but this is not very frequent 'in real life' :)
You can look up the following example code.
I like this paper, which explains how to calculate π based on a Taylor series expansion for Arctangent.
The paper starts with the simple assumption that
Atan(1) = π/4 radians
Atan(x) can be iteratively estimated with the Taylor series
atan(x) = x - x^3/3 + x^5/5 - x^7/7 + x^9/9...
The paper points out why this is not particularly efficient and goes on to make a number of logical refinements in the technique. They also provide a sample program that computes π to a few thousand digits, complete with source code, including the infinite-precision math routines required.
The following link shows how to calculate the pi constant based on its definition as an integral, that can be written as a limit of a summation, it's very interesting:
https://sites.google.com/site/rcorcs/posts/calculatingthepiconstant
The file "Pi as an integral" explains this method used in this post.
First, note that C# can use the Math.PI field of the .NET framework:
https://msdn.microsoft.com/en-us/library/system.math.pi(v=vs.110).aspx
The nice feature here is that it's a full-precision double that you can either use, or compare with computed results. The tabs at that URL have similar constants for C++, F# and Visual Basic.
To calculate more places, you can write your own extended-precision code. One that is quick to code and reasonably fast and easy to program is:
Pi = 4 * [4 * arctan (1/5) - arctan (1/239)]
This formula and many others, including some that converge at amazingly fast rates, such as 50 digits per term, are at Wolfram:
Wolfram Pi Formulas
PI (π) can be calculated by using infinite series. Here are two examples:
Gregory-Leibniz Series:
π/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - ...
C# method :
public static decimal GregoryLeibnizGetPI(int n)
{
decimal sum = 0;
decimal temp = 0;
for (int i = 0; i < n; i++)
{
temp = 4m / (1 + 2 * i);
sum += i % 2 == 0 ? temp : -temp;
}
return sum;
}
Nilakantha Series:
π = 3 + 4 / (2x3x4) - 4 / (4x5x6) + 4 / (6x7x8) - 4 / (8x9x10) + ...
C# method:
public static decimal NilakanthaGetPI(int n)
{
decimal sum = 0;
decimal temp = 0;
decimal a = 2, b = 3, c = 4;
for (int i = 0; i < n; i++)
{
temp = 4 / (a * b * c);
sum += i % 2 == 0 ? temp : -temp;
a += 2; b += 2; c += 2;
}
return 3 + sum;
}
The input parameter n for both functions represents the number of iteration.
The Nilakantha Series in comparison with Gregory-Leibniz Series converges more quickly. The methods can be tested with the following code:
static void Main(string[] args)
{
const decimal pi = 3.1415926535897932384626433832m;
Console.WriteLine($"PI = {pi}");
//Nilakantha Series
int iterationsN = 100;
decimal nilakanthaPI = NilakanthaGetPI(iterationsN);
decimal CalcErrorNilakantha = pi - nilakanthaPI;
Console.WriteLine($"\nNilakantha Series -> PI = {nilakanthaPI}");
Console.WriteLine($"Calculation error = {CalcErrorNilakantha}");
int numDecNilakantha = pi.ToString().Zip(nilakanthaPI.ToString(), (x, y) => x == y).TakeWhile(x => x).Count() - 2;
Console.WriteLine($"Number of correct decimals = {numDecNilakantha}");
Console.WriteLine($"Number of iterations = {iterationsN}");
//Gregory-Leibniz Series
int iterationsGL = 1000000;
decimal GregoryLeibnizPI = GregoryLeibnizGetPI(iterationsGL);
decimal CalcErrorGregoryLeibniz = pi - GregoryLeibnizPI;
Console.WriteLine($"\nGregory-Leibniz Series -> PI = {GregoryLeibnizPI}");
Console.WriteLine($"Calculation error = {CalcErrorGregoryLeibniz}");
int numDecGregoryLeibniz = pi.ToString().Zip(GregoryLeibnizPI.ToString(), (x, y) => x == y).TakeWhile(x => x).Count() - 2;
Console.WriteLine($"Number of correct decimals = {numDecGregoryLeibniz}");
Console.WriteLine($"Number of iterations = {iterationsGL}");
Console.ReadKey();
}
The following output shows that Nilakantha Series returns six correct decimals of PI with one hundred iterations whereas Gregory-Leibniz Series returns five correct decimals of PI with one million iterations:
My code can be tested >> here
Here is a nice way:
Calculate a series of 1/x^2 for x from 1 to what ever you want- the bigger number- the better pie result. Multiply the result by 6 and to sqrt().
Here is the code in c# (main only):
static void Main(string[] args)
{
double counter = 0;
for (double i = 1; i < 1000000; i++)
{
counter = counter + (1 / (Math.Pow(i, 2)));
}
counter = counter * 6;
counter = Math.Sqrt(counter);
Console.WriteLine(counter);
}
public double PI = 22.0 / 7.0;

Categories