I can't figure out how to recursively calculate the rate of return on an investment, where the principal is unknown, and only the rates and the duration of the rates are known.
For example, if I had an investment for 2 years at 10% (or 0.1), the RoR would equal 0.21 (or 21%). This is calculated non-recursively as,
0.21 = 2 * 0.1 + (0.1 ^ 2)
// or
ror = duration * rate + (rate ^ duration)
Since I may not want to only know the final calculation, but the intermittent years of that investment, I must do this recursively (e.g. if the duration is 5 years, I want to know what the rate of return is after the first year, the second year and so on).
Since this is an algorithm, C# isn't required, but that is what I will be programming it in.
The easiest to calculate recursively is 1.0+RoR:
double calculateRateOfReturnPlus1(double rate, int periods) {
if (periods == 0)
return 1.0;
return (1.0 + rate) * calculateRateOfReturnPlus1(rate, periods - 1);
}
This returns 1.21 for rate=0.1, periods=2 and 1.331 for rate=0.1, periods=3. You can then subtract 1.0 to obtain pure RoR. Alternatively, you can compute RoR directly like this:
double calculateRateOfReturn(double rate, int periods) {
if (periods == 0)
return 0.0;
return (1.0 + rate) * (calculateRateOfReturn(rate, periods - 1) + 1.0) - 1.0;
}
Also, you can calculate RoR iteratively like this:
double calculateRateOfReturn(double rate, int periods) {
double RoR = 1.0;
for (int i = 0; i < periods; i++) {
RoR = RoR * (1.0 + rate);
}
return RoR - 1.0;
}
The last two functions return 0.21 for rate=0.1, periods=2 and 0.331 for rate=0.1, periods=3.
In practice one would simply rely on the Math.Pow() function:
double calculateRateOfReturn(double rate, int periods) {
return Math.Pow(1.0+rate, periods) - 1.0;
}
A LINQ version:
double rate = 0.1;
int totalYears = 5;
var results = Enumerable.Range(1, totalYears).Select(i => new { Year = i, RoR = Math.Pow(1 + rate, i) - 1 });
This gives you the rate of return for every year within the period.
I've done similar "modelling" in a spreadsheet, and the easiest way to do this is to calculate the compound interest for every year, and then in another column calculate the difference between successive years.
If you still want to use recursionto calculate yearly (or any other period) you could input the result of the calculation (starting with 1) as the principal for the next period.
So period 0 "rate" would be 1, then period 1 would be 1.1, period 2 would be 1.21 etc.
Related
The title is not really well phrased, I'm aware - can't think of a better way of writing it though.
Here's the scenario - I have two input boxes, both representing integer quantities. One is represented in our units, the other in the vendor's units. There is a multiplier defining how to convert from ours to theirs. In the below example, I'm saying that two of our units is equal to five of theirs. So, for example,
decimal multiplier = 0.4; // Two of our units equals five of theirs
int requestedQuantity = 11; // Our units
int suppliedQuantity = 37; // Their units
// Should return 12, since that is the next highest whole number that results in both of us having whole numbers (12 of ours = 30 of theirs)
int correctedFromRequestedQuantity = GetCorrectedRequestedQuantity(requestedQuantity, null, multiplier);
// Should return 16, since that is the next highest whole number that results in both of us having whole numbers (16 of ours = 40 of theirs);
int correctedFromSuppliedQuantity = GetCorrectedRequestedQuantity(suppliedQuantity, multiplier, null);
Here's the function I've written to handle this. I'm not doing a divide by zero check on the multiplier / rounder since I've already checked for that elsewhere. It seems crazy to do all that converting, but is there a better way of doing it?
public int GetCorrectedRequestedQuantity(int? input, decimal? multiplier, decimal? rounder)
{
if (multiplier == null)
{
if (rounder == null)
return input.GetValueOrDefault();
else
return (int)Math.Ceiling((decimal)((decimal)Math.Ceiling(input.GetValueOrDefault() / rounder.Value) * rounder.Value));
}
else if (input.HasValue)
{
// This is insane...
return (int)Math.Ceiling((decimal)((decimal)Math.Ceiling((int)Math.Ceiling((decimal)input * multiplier.Value) / multiplier.Value) * multiplier.Value));
}
else
return 0;
}
Represent the multiplier as a fraction in lowest terms. I don't know if .NET has a fractions class but if not you can probably find a C# implementation, or just write your own. So assume the multiplier is given by two integers a / b in lowest terms, with a ≠ 0 and b ≠ 0. That also means that conversion in the other direction is given by multiplying by b / a. In your example, a = 2 and b = 5, and a / b = 0.4.
Now suppose you want to convert an integer X. If you think about it a bit you'll see what you really want is to nudge X up until b divides X. The number you need to add to X is simply (b - (X%b)) % b. So to convert on one direction is just
return (a * (X + (b - (X % b) % b))) / b;
and to convert Y going in the other direction is just
return (b * (Y + (a - (X % a) % a))) / a;
My best idea of my head is to semi brute-force it. It does sound like it is basically Fraction Mathematics. So there might be a way easier solution for this.
First we need to find in what sort of "Batch" the multiplier becomes whole. That way, we can stop working with floats/doubles altogether. Ideally this should be supplied with the multiplier (as float math is messy).
double currentMultiple=multiplier;
int currentCount=0;
//This is the best check for "is an integer" could think off.
while(currentMultiple % 1 = 0){
//The Framework can detect Arithmetic Overflow. Let us turn that one on
//If we ever get there, likely the math is non-solveable
checked{
currentMultiple+= multiplier;
currentCount += 1;
}
}
//You get here either via exception or because you got a multiple that solves it.
//Store the value of currentCount into a variable "OurBatchSize"
//Also store the value of currentMultiple in "TheirBatchSize"
Getting the closest Multiple of OurBatchSize:
int requestedQuantity = 11; // Our units
int result = OurBatchSize;
int batchCount = 0;
while(temp < requestedQuantity){
result += OurBatchSize;
batchCount++
}
//result contains the answer here. Return it
//batchCount * TheirBatchSize will also tell you how much they get.
Edit: Credit for this goes mostly to James Reinstate Monica Polk. He had the math idea to use Modulo for this. Here is what I got with explanation:
int result;
int rest = requestedAmout % BatchSize;
if (rest != 0){
//Correct upwards to the next multiple
int DistanceToNextMultiple = BatchSize - Rest;
result = requestedAmout + DistanceToMultiple;
}
else{
//It already is right
result = requestedAmout;
}
For the BatchSize of 4, you will get:
13; 13%4=1; 4-1=3; 13+3=16;
14; 14%4=2; 4-2=2; 14+2=16;
15; 15%4=3; 4-3=1; 15+1=16;
16; 16%4=0; Else is used. 16 is already right.
This might not be the correct place for this, so apologies in advance if it isn't.
My situation - I need to come up with a simple formula/method of giving it an hour E.g. 13, 15, 01 etc, and based on that number, the method will return the 'approx' temperature for that particular time.
This is very approximate and it will not use weather data or anything like that, it will just take the hour of the day and return a value between say -6 deg C > 35 deg C. (very extreme weather, but you get the idea.)
This is the sort of examples I would like to know how to do:
Just as a note, I COULD use an ugly array of 24 items, each referencing the temp for that hour, but this needs to be float based - e.g. 19.76 should return 9.25 deg...
Another note: I don't want a complete solution - I'm a confident programmer in various languages, but the maths have really stumped me on this. I've tried various methods on paper using TimeToPeak (the peak hour being 1pm or around there) but to no avail. Any help would be appreciated at this point.
EDIT
Following your comment, here is a function that provides a sinusoidal distribution with various useful optional parameters.
private static double SinDistribution(
double value,
double lowToHighMeanPoint = 0.0,
double length = 10.0,
double low = -1.0,
double high = 1.0)
{
var amplitude = (high - low) / 2;
var mean = low + amplitude;
return mean + (amplitude * Math.Sin(
(((value - lowToHighMeanPoint) % length) / length) * 2 * Math.PI));
}
You could use it like this, to get the results you desired.
for (double i = 0.0; i < 24.0; i++)
{
Console.WriteLine("{0}: {1}", i, SinDistribution(i, 6.5, 24.0, -6.0, 35.0));
}
This obviously discounts environmental factors and assumes the day is an equinox but I think it answers the question.
So,
double EstimatedTemperature(double hour, double[] distribution)
{
var low = Math.Floor(hour);
var lowIndex = (int)low;
var highIndex = (int)Math.Ceiling(hour);
if (highIndex > distribution.Count - 1)
{
highIndex = 0;
}
if (lowIndex < 0)
{
lowIndex = distribution.Count - 1;
}
var lowValue = distribution.ElementAt(lowIndex);
var highValue = distribution.ElementAt(highIndex);
return lowValue + ((hour - low) * (highValue - lowValue));
}
assuming a rather simplistic linear transition between each point in the distibution. You'll get erroneous results if the hour is mapped to elements that are not present in the distribution.
For arbitrary data points, I would go with one of the other linear interpolation solutions that have been provided.
However, this particular set of data is generated by a triangle wave:
temp = 45*Math.Abs(2*((t-1)/24-Math.Floor((t-1)/24+.5)))-10;
The data in your table is linear up and down from a peak at hour 13 and a minimum at hour 1. If that is the type of model that you want then this is really easy to put into a formulaic solution. You would just simply perform linear interpolation between the two extremes of the temperature based upon the hour value. You would have two data points:
(xmin, ymin) as (hour-min, temp-min)
(xmax, ymax) as (hour-max, temp-max)
You would have two equations of the form:
The two equations would use the (x0, y0) and (x1, y1) values as the above two data points but apply them the opposite assignment (ie peak would be (x0, y0) on one and (x1, y1) in the other equation.
You would then select which equation to use based upon the hour value, insert the X value as the hour and compute as Y for the temperature value.
You will want to offset the X values used in the equations so that you take care of the offset between when Hour 0 and where the minimum temperature peak happens.
Here is an example of how you could do this using a simple set of values in the function, if you wish, add these as parameters;
public double GetTemp(double hour)
{
int min = 1;
int max = min + 12;
double lowest = -10;
double highest = 35;
double change = 3.75;
return (hour > max) ? ((max - hour) * change) + highest : (hour < min) ? ((min - hour)*change) + lowest : ((hour - max) * change) + highest;
}
I have tested this according to your example and it is working with 19.75 = 9.6875.
There is no check to see whether the value entered is within 0-24, but that you can probably manage yourself :)
You can use simple 2 point linear approximation. Try somthing like this:
function double hourTemp(double hour)
{
idx1 = round(hour);
idx2 = idx1 + 1;
return (data[idx2] - data[idx1]) * (hour - idx1) + data[idx1];
}
Or use 3,5 or more points to get polynom cofficients with Ordinary Least Squares method.
Your sample data similar to the sin function so you can make sin function approximation.
I have a need to create a graph, where the scale of the Y-axis changes depending on the data input into the system. Conceivably this scale could be anywhere from 0-10, 0-100, or even have bottom limit of thousands and an upper limit of millions.
To properly determinethe scale of this axis, I need to work out the ratio of Points to Pixels (based on graph height/range).
Now a graphs' axis never start at the lowest value and go to the highest, usual practice is to go to the next nearest 2, 5 or 10 (above for upper limit, and below for lower) depending on the range of values.
So what I'd like to know is how to take the max value from the data set, and round it up to the nearest 10.
for clarification, the input values will always be integers.
what i have now is this
if ((rangeMax < 10) && (rangeMax > 5))
rangeMax = 10;
else if (rangeMax < 5)
rangeMax = 5;
Which is only useful for values less than 10, and doesn't allow the flexibility required to be truly dynamic. Ultimately this graph will be auto-generated during a page load event, with no user input.
I've read around a bit, and people talk about things like the modulus operator (%), but I can't find any reliable information about it's use, and talk of Math.Ceiling and Math.Round, but these go to the next nearest whole number, which isn't quite there, and don't seem to help much at all when dealing with integers anyway.
Any suggestions, pointers or help greatly appreciated.
i did find a similar question asked here How can i get the next highest multiple of 5 or 10 but i don't know java, so i can't understand any of what was said.
Cheers
if(rangeMax % 10 !=0)
rangeMax = (rangeMax - rangeMax % 10) + 10;
You could also use Math.Round() with MidpointRounding.AwayFromZero using a decimal number (otherwise integer division will truncate fractions):
decimal number = 55M;
decimal nextHighest = Math.Round(number/ 10, MidpointRounding.AwayFromZero) * 10;
If you want to go up to the next 10, you can use Math.Ceiling as follows:
rangeMax = (int)(Math.Ceiling((decimal)rangeMax / 10) * 10);
If you need to generalize to go to the next n (for example 5 here) you can do:
int n = 5;
rangeMax = (int)(Math.Ceiling((decimal)rangeMax / n) * n);
Something which might help is to divide the number by 10. This should round it to the nearest integer. Then multiply it by 10 again to get the number rounded to the nearest 10
I use THIS:
public static double RoundTo10(double number)
{
if (number > 0)
{
return Math.Ceiling(number / 10) * 10;
}
else
{
return Math.Floor(number / 10) * 10;
}
}
you can try this....
decimal val = 95;
//decimal val =Convert.ToDecimal( textBox1.Text);
decimal tmp = 0;
tmp = (val % 10);
//MessageBox.Show(tmp.ToString()+ "Final val:"+(val-tmp).ToString());
decimal finval = val - tmp;
I have a decimal number which can be like the following:
189.182
I want to round this up to 2 decimal places, so the output would be the following:
189.19
Is there built in functionality for this in the Math class, or something else? I know the ceiling function exists but this doesn't seem to do what I want - it'll round to the nearest int, so just '189' in this case.
Multiply by 100, call ceiling, divide by 100 does what I think you are asking for
public static double RoundUp(double input, int places)
{
double multiplier = Math.Pow(10, Convert.ToDouble(places));
return Math.Ceiling(input * multiplier) / multiplier;
}
Usage would look like:
RoundUp(189.182, 2);
This works by shifting the decimal point right 2 places (so it is to the right of the last 8) then performing the ceiling operation, then shifting the decimal point back to its original position.
You can use:
decimal n = 189.182M;
n = System.Math.Ceiling (n * 100) / 100;
An explanation of the various rounding functions can be found here.
Be aware that formulae like this are still constrained by the limited precision of the double type, should that be the type you are using (your question stated decimal but it's possible you may just have meant a floating point value with fractional component rather than that specific type).
For example:
double n = 283.79;
n = System.Math.Ceiling (n * 100);
will actually give you 28380, not the 283.79 you would expect(a).
If you want accuarate results across the board, you should definitely be using the decimal type.
(a) This is because the most accurate IEEE754 double precision representation of 283.79 is actually:
283.790000000000020463630789891
That extra (admittedly minuscule) fractional component beyond the .79 gets ceilinged up, meaning it will give you a value higher than you would expect.
var numberToBeRound1 = 4.125;
var numberToBeRound2 = 4.175;
var numberToBeRound3 = 4.631;
var numberToBeRound4 = 4.638;
var numberOfDecimalPlaces = 2;
var multiplier = Math.Pow(10, numberOfDecimalPlaces);
//To Round Up => 4.13
var roundedUpNumber = Math.Ceiling(numberToBeRound1 * multiplier) / multiplier;
//To Round Down => 4.12
var roundedDownNumber = Math.Floor(numberToBeRound1 * multiplier) / multiplier;
//To Round To Even => 4.12
var roundedDownToEvenNumber = Math.Round(numberToBeRound1, numberOfDecimalPlaces, MidpointRounding.ToEven);
//To Round To Even => 4.18
var roundedUpToEvenNumber = Math.Round(numberToBeRound2, numberOfDecimalPlaces, MidpointRounding.ToEven);
//To Round To Away From Zero => 4.63
var roundedDownToAwayFromZero = Math.Round(numberToBeRound3, numberOfDecimalPlaces, MidpointRounding.AwayFromZero);
//To Round To Away From Zero => 4.64
var roundedUpToAwayFromZero2 = Math.Round(numberToBeRound4, numberOfDecimalPlaces, MidpointRounding.AwayFromZero);
How about
0.01 * ceil(100 * 189.182)
In .NET Core 3.0 and later versions, three additional rounding strategies are available through the MidpointRounding enumeration.
Besides MidpointRounding.AwayFromZero and MidpointRounding.ToEven it now includes:
1. MidpointRounding.ToNegativeInfinity
2. MidpointRounding.ToPositiveInfinity
3. MidpointRounding.ToZero
For this specific question you need to use MidpointRounding.ToPositiveInfinity, this will round the number up always.
Note this only works if the number isn't negative. See table below for examples.
Original number
ToNegativeInfinity
ToPositiveInfinity
ToZero
3.55
3.5
3.6
3.5
2.83
2.8
2.9
2.8
2.54
2.5
2.6
2.5
2.16
2.1
2.2
2.1
-2.16
-2.2
-2.1
-2.1
-2.54
-2.6
-2.5
-2.5
-2.83
-2.9
-2.8
-2.8
-3.55
-3.6
-3.5
-3.5
For more information about midpointrounding see https://learn.microsoft.com/en-us/dotnet/api/system.midpointrounding
And of course the code to make it work:
// function explained: Math.Round(number, amount of decimals, MidpointRounding);
decimal number = 189.182m;
number = Math.Round(number, 2, MidpointRounding.ToPositiveInfinity);
// result: number = 189.19
public static decimal RoundUp(decimal input, int places)
{
decimal multiplier = (decimal)Math.Pow(10, places);
return decimal.Ceiling(input * multiplier) / multiplier;
}
// Double will return the wrong value for some cases. eg: 160.80
public static decimal RoundUp(decimal input, int places)
{
decimal multiplier = Convert.ToDecimal(Math.Pow(10, Convert.ToDouble(places)));
return Math.Ceiling(input * multiplier) / multiplier;
}
One other quirky but fun way to do it is Math.Round() after offsetting the number.
decimal RoundUp(decimal n, int decimals)
{
n += decimal.Parse($"1e-{decimals}", System.Globalization.NumberStyles.AllowExponent) / 2;
n -= 1e-28m;
return Math.Round(n, decimals);
}
decimal RoundDown(decimal n, int decimals)
{
n -= decimal.Parse($"1e-{decimals}", System.Globalization.NumberStyles.AllowExponent) / 2;
n += 1e-28m;
return Math.Round(n, decimals);
}
Is has the advantage of not using Math.Pow() which uses double and thus can cause unpredictable rounding errors.
This solution basically uses the fact that midpoint rounding can be turned into up/down rounding if you increase/decrease the number a little:
Math.Round(3.04m, 1) is 3.0 - not what we want
Let's add 0.04(9) to it
Math.Round(3.0899999999999999999999999999m, 1) is 3.1 - success!
Subtracting 1e-28m (= 0.0000000000000000000000000001) is important, because we want to be able to round up 3.0000000000000000000000000001 to 4, but 3.0000000000000000000000000000 should stay 3.
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;