Riemann Midpoint Sum getting crazy numbers - c#

I'm working on a Midpoint Riemann Sum program, and it finds the integral of a randomly generated function called f.
Here's what wrote:
public static double FindIntegral (double start, double end, function f)
{
double sum = 0;
double stepsize = 1E-2;
int numSteps = (int)((end - start) / stepsize);
for (int i = 0; i < numSteps; i++)
{
sum += f(start + (stepsize * (i + 0.5)));
}
return sum * stepsize;
}
The function returns numbers that are too low (I have a reliable checking mechanism).
I put in x^3 for f, and I got the right answer. I tried a couple of more integrable functions and got a good answer. But somehow once I put in f it doesn't work.

I got the math formula for "Riemann Midpoint Sum" from here.
My implementation below seems to get the right answer (using the example function on the page). I used a class because 1) I could make the algorithm work specifying either the step size or the number of rectangles (I preferred the latter) and 2) I didn't see any reason to hard-code either into the algorithm.
As it turns out your code seemed to work just fine (see below); Make sure the code you have here in your question is what you're executing and make sure your expected result is accurate and that you're supplying good inputs (i.e. you don't have start and end backwards or the wrong function f or something). In other words what you provided in your question looks fine. Note double is approximate in C# (floating point arithmetic, in general) so to compare equality you can't use == unless you want exact if you're using unit tests or something.
public class Program
{
public static void Main()
{
function f = x => 50 / (10 + x * x);
// 9.41404285216233
Console.Out.WriteLine(new RiemannMidpointSum(6).FindIntegral(1, 4, f));
// 9.41654853716462
Console.Out.WriteLine(new RiemannMidpointSum(1E-2).FindIntegral(1, 4, f));
// 9.41654853716462
Console.Out.WriteLine(Program.FindIntegral(1, 4, f));
}
// This is your function.
public static double FindIntegral (double start, double end, function f)
{
double sum = 0;
double stepsize = 1E-2;
int numSteps = (int)((end - start) / stepsize);
for (int i = 0; i < numSteps; i++)
{
sum += f(start + (stepsize * (i + 0.5)));
}
return sum * stepsize;
}
}
public delegate double function(double d);
public class RiemannMidpointSum
{
private int? _numberOfRectangles;
private double? _widthPerRectangle;
public RiemannMidpointSum(int numberOfRectangles)
{
// TODO: Handle non-positive input.
this._numberOfRectangles = numberOfRectangles;
}
public RiemannMidpointSum(double widthPerRectangle)
{
// TODO: Handle non-positive input.
this._widthPerRectangle = widthPerRectangle;
}
public double FindIntegral(double a, double b, function f)
{
var totalWidth = b - a;
var widthPerRectangle = this._widthPerRectangle ?? (totalWidth / this._numberOfRectangles.Value);
var numberOfRectangles = this._numberOfRectangles ?? ((int)Math.Round(totalWidth / this._widthPerRectangle.Value, 0));
double sum = 0;
foreach (var i in Enumerable.Range(0, numberOfRectangles))
{
var rectangleMidpointX = a + widthPerRectangle * i + widthPerRectangle / 2;
var rectangleHeightY = f(rectangleMidpointX);
var rectangleArea = widthPerRectangle * rectangleHeightY;
sum += rectangleArea;
}
return sum;
}
}

Related

Specify a starting index for continuation of calculating Pi

This C# code will calculate Pi to whatever length I specify. I want to be able to start at a given index without recalculating to that point. Precision is not a great concern as this is a puzzle project but I do need this code to reproduce the same results over and over. It works fine as is but I haven't been able to figure out how to modify for a starting point.
//Looking to pass BigInteger to specify a starting index for continuation of calculating Pi
public static BigInteger GetPi(int digits, int iterations)
{
return 16 * ArcTan1OverX(5, digits).ElementAt(iterations)
- 4 * ArcTan1OverX(239, digits).ElementAt(iterations);
}
public static IEnumerable<BigInteger> ArcTan1OverX(int x, int digits)
{
var mag = BigInteger.Pow(10, digits);
var sum = BigInteger.Zero;
bool sign = true;
for (int i = 1; true; i += 2)
{
var cur = mag / (BigInteger.Pow(x, i) * i);
if (sign)
{
sum += cur;
}
else
{
sum -= cur;
}
yield return sum;
sign = !sign;
}
}
You are using the Machin formula with the Taylor serie expansion for Arctan. It should give you about 1.4 digits of precision for each "cycle" (see here). You can't "shortcut" the calculation of the Taylor serie. You can speed-up a little the program removing the IEnumerable<BigInteger> part and simply returning the nth iteration (the yield instruction has a cost) and by changing the BigInteger.Pow with a fixed multiplication. But the calculation will still be made iteratively. There is no known way for calculating PI with a precision of n digits in O(1) time.
Note that there are algorithms (see the wiki) that converge in a smaller number of cycles, but I'm not sure if they converge in a smaller number of operations (their cycles are much more complex).
An optimized version of the code:
public static BigInteger GetPi2(int digits, int iterations)
{
return 16 * ArcTan1OverX2(5, digits, iterations)
- 4 * ArcTan1OverX2(239, digits, iterations);
}
public static BigInteger ArcTan1OverX2(int x, int digits, int iterations)
{
var mag = BigInteger.Pow(10, digits);
var sum = BigInteger.Zero;
bool sign = true;
int imax = 1 + (2 * iterations);
int xsquared = x * x;
BigInteger pow = x;
for (int i = 1; i <= imax; i += 2)
{
if (i != 1)
{
pow *= xsquared;
}
var cur = mag / (pow * i);
if (sign)
{
sum += cur;
}
else
{
sum -= cur;
}
sign = !sign;
}
return sum;
}

Implementing partial recursive function in C#

I am having trouble with somwhow implementing a partial recursive function (at least in my mind though).
for any given p and arbitrary maxsteps = 100, calculate L:
You could pass the maxsteps down to the recursive function and subtract 1 on each step until you reach 0, with is the end condition:
public double L(double p, int maxSteps)
{
if (maxSteps == 0)
{
return 1 / (p + 1);
}
return 1 / (p + L(p, maxSteps - 1));
}
I appreciate you want a recursive function, but I figured I'd provide a non-recursive alternative in case it turns out to be preferred:
private static double CalculateL(double p, int maxsteps)
{
double val = 1 / (p + 1);
for (int i = 1; i <= maxsteps; ++i)
{
val = 1 / (p + val);
}
return val;
}
I'm not 100% sure about maxsteps, based on the other answers. If the answer isn't right, then you probably want < maxsteps where I've got <= maxsteps.
Also, please read Is floating point math broken? if you're expecting very precise results.
There I left you the code for the recursive approach:
class Program
{
static void Main(string[] args)
{
double recursiveL = CalculateL(100, 100);
double notRecursiveLWrong = NotRecursiveCalculateLWrong(100, 100);
double notRecursiveLRight = NotRecursiveCalculateLRight(100, 100);
}
private static double CalculateL(double p, int maxSteps)
{
if (maxSteps == 0)
{
return (1 / (p + 1));
}
else
{
return (1 / (p + CalculateL(p, maxSteps - 1)));
}
}
private static double NotRecursiveCalculateLWrong(double p, int maxSteps)
{
double result = 0;
for (int i = 0; i < maxSteps; i++)
{
result = (1 / (p + result));
}
return result;
}
private static double NotRecursiveCalculateLRight(double p, int maxSteps)
{
double result = 1 / (p + 1);
for (int i = 0; i < maxSteps; i++)
{
result = (1 / (p + result));
}
return result;
}
}
While making it I was thinking about the fact that for this problem, recursion isn't needed and now I can see that I'm not the only one.
I added my not recursive approach.
Edit:
If you try my code you will see that every method returns the same value, WATCHOUT, this is cause of the low precision in floating points.
The correct approach is NotRecursiveCalculateLRight which is stated in #John 's answer.

Summing infinite series 1/n

I just started taking my first steps in learning coding and general (starting with c#)and I'm learning from a book currently. The book leaves questions at the end of every chapter. I'm currently unsure on how to proceed with this specific question. The question is as follows:
Question: Write a program that calculates the sum (with precision of 0.001) of the following sequence: 1 + 1/2 - 1/3 + 1/4 - 1/5 + … 1/n
The book has given the following guidelines for this problem:
Guide Lines: Accumulate the sum of the sequence in a variable inside a while-loop (see the chapter "Loops"). At each step compare the old sum with the new sum. If the difference between the two sums Math.Abs(current_sum – old_sum) is less than the required precision (0.001), the calculation should finish because the difference is constantly decreasing and the precision is constantly increasing at each step of the loop. The expected result is 1.307
I have an idea on how to implement this but I do not know how or where to initiate and break the loop when the sum has reached the required precision. I currently use user input to enter n. I would like to know how to automate this process.
Here is my code so far. I know its a cop out to use the format {N:2} but i am not sure how to proceed. Would very much appreciate the help! Thanks!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
static void Main()
{
Console.Write("Please enter n: ");
double counter = double.Parse(Console.ReadLine());
double sum = 1 + AddSum(counter); // calculate infinite sum
Console.WriteLine("Sum = {0:N3}", sum);
}
static double AddSum(double n)
{
double a = 0;
for (double i = 1; i < n; i++)
{
if(i % 2 == 0)
{
a -= 1 / (i +1); // calculates negative fractions
}
else
{
a += 1 / (i +1); // calculates positive fractions
}
}
return a;
}
}
Here's an example that doesn't suffer from subtractive cancellation:
static double AddSum()
{
double pos = 1.0;
double neg = 0.0;
double delta = 0.001;
double current = pos + neg;
double previous = pos + 2.0 * delta;
int i = 2;
while (Math.Abs(current - previous) >= delta)
{
if (i % 2 == 0)
{
pos += 1.0 / i;
}
else
{
neg -= 1.0 / i;
}
previous = current;
current = pos + neg;
i++;
}
return current;
}
You may want to follow the given guideline: don't enter n as the program shall finish automatically. Where is the suggested while loop? You'll figure the answer out quickly yourself then :-)
Maybe start with this:
static void Main()
{
decimal result = 1;
int n = 1;
do
{
// remember the current result
result += 1 / (++n * DetermineMultiplier(n));
} while ( /* precision calculation here */ );
// print result and n
}
private int DetermineMultiplier(int n)
{
// return -1 if n is odd, 1 if it is even
}
As you not want to specify n and the only exit condition is a precision check, you could do this.
static double AddSum()
{
double a = 0;
double oldvalue;
int i = 1;
do
{
oldvalue = a;
a += (i % 2 == 0) ? (double)-1 / (i + 1) : (double)1 / (i + 1);
i++;
}while (!(i != 1 && Math.Abs(a - oldvalue) < 0.0001)); // we can remove i!=1 if we know and hard code first default value
return a;
}
Working Example

How to shift all the whole numbers in a double to the right of the point

How to shift all the whole numbers in a double to the right of the point ?
Example i have 5342, i want the function to return 0.5342. I do not know the number of digits in the double, it's randomly generated. Should be fairly easy but i can't find any answers.
private static void Main(string[] args)
{
Console.WriteLine(MyFunction(5127));
Console.WriteLine(MyFunction(1));
Console.WriteLine(MyFunction(51283271));
Console.WriteLine(MyFunction(-512));
Console.WriteLine(MyFunction(0));
}
public static double MyFunction(double myNumber)
{
return Math.Floor(myNumber) / Math.Pow(10, Math.Abs(myNumber).ToString().Length);
}
This sounds like a pretty bizarre task, to be honest, but you could use:
while (Math.Abs(value) >= 1)
{
value = value / 10;
}
That will go into an infinite loop if the input is infinity though - and you may well lose information as you keep dividing. The latter point is important - if what you're really interested in is the decimal representation, you should consider using decimal instead of double.
You could potentially use a mixture of Math.Log and Math.Pow to do it, but the above is probably what I'd start with.
This will get you most of the way there
public static string test()
{
double dub = 5432;
string dubTxt = dub.ToString();
string text = "0.";
string test = string.Concat(text + dubTxt);
if (1 == 1)
{
MessageBox.Show(test);
return test;
}
}
You will have to develop more if statements to handle the negative numbers.
public static string test()
{
double dub = 5432;
string dubTxt = dub.ToString();
string text = "0.";
string test = string.Concat(text + dubTxt);
if (dub < 0)
{
//Do this code instead
}
}
Good Luck. Please bump me if you choose it!! I need the cred so I can do other junk. :-D
Just divide by 10 until the number is less than 1.
public static double SomeMethod(double n)
{
double d = n;
bool isNegative = (d < 0);
if(isNegative)
d = d * -1;
while(d >= 1)
d = d/10;
if(isNegative)
d = d * -1;
return d;
}
Alternative (and more precise) option:
public static double SomeMethod2(double n)
{
double d = n;
bool isNegative = (d < 0);
if(isNegative)
d = d * -1;
int numberOfDigits = ((int)d).ToString().Length;
int divisor = 1;
for(int i = 0; i < numberOfDigits; i++)
divisor = divisor * 10;
d = d/divisor;
if(isNegative)
d = d * -1;
return d;
}

More efficient Integration Loop

public double Integral(double[] x, double intPointOne, double intPointTwo)
{
double integral = 0;
double i = intPointOne;
do
{
integral += Function(x[i])*.001;
i = i + .001;
}
while (i <= intPointTwo);
return integral;
}
Here's a function I have to integrate a function from x1-x2 simply using a summation of parts. How can I make this loop more efficient (using less loops), but more accurate?
Where Function changes every iteration, but it should be irrelevant as it's order of magnitude (or boundary) should stay relatively the same...
1) look into section 4.3 of http://apps.nrbook.com/c/index.html for a different algorithm.
2) To control the accuracy/speed factor you may need to specify the bounds x_low and x_high as well as how many slices you want in the integral. So your function would look like this
// Integrate function f(x) using the trapezoidal rule between x=x_low..x_high
double Integrate(Func<double,double> f, double x_low, double x_high, int N_steps)
{
double h = (x_high-x_low)/N_steps;
double res = (f(x_low)+f(x_high))/2;
for(int i=1; i < N; i++)
{
res += f(x_low+i*h);
}
return h*res;
}
Once you understand this basic integration, you can move on to more elaborate schemes mentioned in Numerical Recipies and other sources.
To use this code issue a command like A = Integrate( Math.Sin, 0, Math.PI, 1440 );
Here the calculation of the integral through methods: left hand, trapezoidal and mid point
/// <summary>
/// Return the integral from a to b of function f
/// using the left hand rule
/// </summary>
public static double IntegrateLeftHand(double a,
double b,
Func<double,double> f,
int strips = -1) {
if (a >= b) return -1; // constraint: a must be greater than b
// if strips is not provided, calculate it
if (strips == -1) { strips = GetStrips(a, b, f); }
double h = (b - a) / strips;
double acc = 0.0;
for (int i = 0; i < strips; i++) { acc += h * f(a + i * h); }
return acc;
}
/// <summary>
/// Return the integral from a to b of function f
/// using the midpoint rule
/// </summary>
public static double IntegrateMidPoint(double a,
double b,
Func<double, double> f,
int strips = -1) {
if (a >= b) return -1; // constraint: a must be greater than b
// if strips is not provided, calculate it
if (strips == -1) { strips = GetStrips(a, b, f); }
double h = (b - a) / strips;
double x = a + h / 2;
double acc = 0.0;
while (x < b)
{
acc += h * f(x);
x += h;
}
return acc;
}
/// <summary>
/// Return the integral from a to b of function f
/// using trapezoidal rule
/// </summary>
public static double IntegrateTrapezoidal(double a,
double b,
Func<double, double> f,
int strips = -1) {
if (a >= b) return -1; // constraint: a must be greater than b
// if strips is not provided, calculate it
if (strips == -1) { strips = GetStrips(a, b, f); }
double h = (b - a) / strips;
double acc = (h / 2) * (f(a) + f(b));
for (int i = 1; i < strips; i++) { acc += h * f(a + i * h); }
return acc;
}
private static int GetStrips(double a,
double b,
Func<double, double> f) {
int strips = 100;
for (int i = (int)a; i < b; i++)
{
strips = (strips > f(i)) ? strips : (int)f(i);
}
return strips;
}
Console.WriteLine("w/ strips:{0}", IntegrateLeftHand(0, 3.14, Math.Sin, 1440));
Console.WriteLine("without strips:{0}", IntegrateMidPoint(0, 30, x => x * x));
// or with a defined method for f(x)
public static double myFunc(x) { return x * (x + 1); }
Console.WriteLine("w/ strips:{0}", IntegrateLeftHand(0, 20, myFunc, 200));
If you know functions in advance than you can analyze them and see what integration steps size works for your purposes. I.e. for linear function you need just one step, but for other functions you may need variable steps. At least see if you can get away with something like (pointTwo - pointOne)/1000.0.
If you need it for generic function and it is not homework you should strongly consider existing libraries or refreshing on your first-second year math courses...
Note your code actually have bug of not using i (which is very bad name for x):
for(x=intPointOne; x<=intPointTwo;x+=0.001)
{
integral += Function(x)*.001;
}
You are using the left-hand rule for integrating. This is only semi-accurate as long as the function has a positive and negative slope across the domain (since the errors of using the left end point cancel out).
I would recommend, at least, moving to the trapezoidal rule (calculate the area under the trapezoid formed by the set (x[i], 0), (x[i+0.001], 0), (x[i], Function(x[i]), (x[i+0.001], Function(x[x+0.001]).
An even better solution is to use Simpson's rule. It is a slower algorithm, but the accuracy should allow you to significantly increase your interval.
Look here: Numerical Integration for details.

Categories

Resources