C# trapezoidal rule sum of y value - c#

Our teacher asked us to use C# to do a trapezoidal rule solution;
He wants us to break it down into three methods.
Below is the the question and my code so far:
Numerical integration is a technique that is particular suitable for
computer applications. In exercise we will try to implement the
trapezoidal rule. The integral of a mathematical function is the area
between the curve and the x-axis. If the area is divided into little
trapezoids, then the integral is approximated by the area of these
geometrical figures.
You will try to find the area under the curve y = 6x^2-7x+2 in the
region from x = 0.5 to x = 1.5 (N.B. your answer should work out to
about be 1.54, however the actual answer is 1.5). The area is given by
the formula
where y0 and y1 are the height of the vertical lines i.e. the value of
the function.
This problem can be decomposed into three parts as follows:
Write a method called EvaluateQuadraticValue(double x, double a, double b, double c) that takes four double arguments: the value of x,
the coefficient of the x2 term, the coefficient of the x and the
constant. The method will compute and return the result value of y
given by the expression y = ax2+ba+c.
Write a method called ComputeQuadraticValues(double startX, double increments, int numberOfIntervals, double a, double b, double c) that
takes six arguments: the start value of x, the increments and the
number of intervals and the coefficients of the quadratic equation.
This method will figure out the values of x0, x1, x2 etc. by invoking
the previous question. The results of the methods calls are collected
and returned as a double array.
Write a method called ApplyTrapeziodalRule(double startX, double endX, int numberOfIntervals, double a, double b, double c) . The
arguments are described in the previous question. This method calls
the previous method and process the double array that is returned to
compute the area under the curve by applying the formula
And my code so far:
public static double EvaluateQuadraticValue(double x, double a, double b, double c)
{
double y = a * Math.Pow(x, 2) + b * x + c;
Console.WriteLine("The y coordinate for this x is: {0}", y);
return y;
}
public static double[] ComputeQuadraticValues(double startX, double increments, int numberOfIntervals, double a, double b, double c)
{
double[] xPoints = new double[numberOfIntervals];
for (int index = 0; index < numberOfIntervals; index++)
{
xPoints[index] = startX;
Console.WriteLine("X{0} is {1}: ",index, xPoints[index]);
EvaluateQuadraticValue(startX, a, b, c);
startX = startX + increments;
}
return xPoints;
}
public static void ApplyTrapeziodalRule(double startX, double endX, int numberOfIntervals, double a, double b, double c)
{
double increments = Convert.ToInt32(Console.ReadLine());
double[] xPoints = ComputeQuadraticValues(startX, increments, numberOfIntervals, a, b, c);
//double[] values = a * Math.Pow(xPoints[i], 2) + b * xPoints[i] + c;
//double y = xPoints.Sum();
/*for (int i = 0; i < numberOfIntervals; i++)
{
}*/
//Console.WriteLine(y + " sum");
}
Currently I'm having trouble with the third method.
Since my double array from ComputeQuadraticValues() are x0, x1, x2 etc. How do I use this array to get (y0 + 2*y1 + 2*y2 + ...... + 2*yn + y(n+1))?
Any hints or tips are appreciated!

I agree with #MartinLiversage and also think there are some other tricky parts in the excersise. I'll try to do my best giving you a good answer. Let me know how this works for you.
This is the curve represented by 6x^2-7x+2 and you're required to compute the area in blue:
What you're doing is a numerical method, and the logic behind is that if you manage to split the area in an infinite number of points, you'll get the total area more accurately. The more points you add, more accurate the result will be.
The thing is that in Computer Sciences, infinity is not possible, because resources are limited and eventually you'll need to set a limit.
I've set 10 as number of interval (N) so you'll get 11 points and the sample is readable.
Now, your first method is just the helper in order to evaluate a function in the form ax^2 + bx + c.
public static double EvaluateQuadraticValue(double x, double a, double b, double c)
{
double y = a*Math.Pow(x,2) + b*x + c;
return y;
}
The second is where I think the problem is. I'd implement it like this:
public static double[] ComputeQuadraticValues(double startX, double increments, int numberOfIntervals, double a, double b, double c)
{
//We need numberOfInterval + 1 values
double[] yPoints = new double[numberOfIntervals+1];
for (int index = 0; index <= numberOfIntervals; index++, startX += increments)
{
//evaluate the function and get the y value for this x
yPoints[index] = EvaluateQuadraticValue(startX, a, b, c);
//Console.WriteLine("({0}, {1})", startX, yPoints[index]);
}
return yPoints;
}
And the last is the one who gets called by your Main() function:
public static void ApplyTrapezoidalRule(double startX, double endX, int numberOfIntervals, double a, double b, double c)
{
double increments = (endX - startX)/numberOfIntervals;
Console.WriteLine("increment: " + increments);
//compute the function value for each X (generated from startX + increment).
double[] yPoints = ComputeQuadraticValues(startX, increments, numberOfIntervals, a, b, c);
var first = (double)(endX - startX)/(2*numberOfIntervals);
Console.WriteLine("({0} - {1})/2*{2} = {3}", endX, startX, numberOfIntervals, first);
var sum = yPoints[0];
for (int i = 1; i <= numberOfIntervals; i++)
sum += 2 * yPoints[i];
sum += yPoints[numberOfIntervals];
var result = first * sum;
Console.WriteLine("result: " + result);
}
I've declared more variables so you'll see the process and the code is again more readable.
You can see this fiddle and play with the numberOfIntervals you pass in. Note that the value will be more accurate if you increase the number of intervals.
Hope this helps!

To me the description of ComputeQuadraticValues is confusing. It would make sense if it returned y0, y1, y2 etc. and not x0, x1, x2 etc. as stated.
Looking at your code for ComputeQuadraticValues you call EvaluateQuadraticValue (which computes y given x). However, the computed y value is not stored anywhere. You can rename xPoints to yPoints and then store the computed y value in that array before returning it as the result of the function.
With that change you should then be able to write a working version of ApplyTrapeziodalRule.

Related

How to calculate the marks above and below the average using Generic in C#?

I am trying to solve this question :
Create a function of type Generic so that it receives 5 marks, regardless of the type of these marks. Calculate the average, calculate the marks above and below the average, and print the result on the screen.
but I did not know how! , I do this but I don't know how to display the marks above and below the average.
and I am not sure if I solve the question in the right way.
using System;
namespace oopGeneric
{
class Calculator
{
public int high = 0, low = 0;
public double Sum<A, B, C, D, E>(int n1, double n2, double n3, int n4, int n5)
{
double sum = n1 + n2 + n3 + n4 + n5;
Console.WriteLine("The Summation {0} ", sum);
double avg = sum / 5;
return avg;
}
class Program
{
static void Main(string[] args)
{
Calculator calc = new Calculator();
double sum = calc.Sum<int, double, double, int, int>(5, 5.5, 15.0, 6, 8);
// Console.WriteLine("above" + high);
Console.WriteLine(sum);
}
}
}
}
In the method Sum, you can insert the code
double avg = sum / 5;
var marks = new double[]{n1,n2,n3,n4,n5};
foreach (double m in marks)
if (m > avg) Console.WriteLine(m);
You will get the marks above the average.
This is the solution using matching pattern.
public double Sum<A, B, C, D, E>(A n1, B n2, C n3, D n4, E n5)
{
double sum = 0;
sum+= (n1 is Int32 n1_as_integer) ? n1_as_integer :
(n1 is Double n1_as_double) ? n1_as_double : 0;
sum+= (n2 is Int32 n2_as_integer) ? n2_as_integer :
(n2 is Double n2_as_double) ? n2_as_double : 0;
return sum / 5;
}
This is the solution using params + matching pattern.
public double Sum(params object[] N)
{
double sum = 0;
foreach(var i in N)
sum+= (i is Int32 i_as_integer) ? i_as_integer :
(i is Double i_as_double) ? i_as_double : 0;
return (N.Lenght>0) ? sum / N.Lenght : 0;
}
You may want to consider accepting any IConvertible object as a generic constraint.
IConvertible
An object that implements IConvertible is required to implement public methods that either convert to the designated primitive runtime type(such as int, float) or throw an InvalidCastException.
These types include
bool sbyte byte
u/short u/int u/long
double float decimal Single
DateTime char string
We can use IConvertible as a constraint to allow only objects that can be converted to primitives.
For example we could convert any of the above types(except the ones that aren't numbers they will throw InvalidCastException) to a double with this method.
double Convert<T>(T Value) where T : IConvertible
{
return Value.ToDouble(null);
}
// These all work
Convert(10m); // (decimal)
Convert(10); // (int)
Convert(10f); // (float)
Convert((sbyte)10);
Convert((long)10);
Using this we can construct an average function that can accept an atrocity such as this:
Average<IConvertible>(10, 10m, (ushort)10, (byte)10, (sbyte)10, 10f, 10d, (long)10, (ulong)10, (uint)10);
Which if we did everything right should ideally output 10d;
public double Average<T>(params T[] numbers) where T : IConvertible
{
// create a place to put the sum, since we need it to calculate the average later
double sum = default;
// store the length of the array since we use it in multiple places
int count = numbers.Length;
for (int i = 0; i < count; i++)
{
// convert value to double, all primitive IConvertible types are required to cast to double(generally)
double value = numbers[i].ToDouble(null);
// add value to the sum so we can calculate the average later
sum += value;
}
// return the average score
return sum / (double)count; // cast int to double to avoid unintentional integer math
}
Editors Note
The above example assumes the requirement to use Generics. You can simplify the un-intuitive call for Average<IConvertible> for mixed-types with a solution such as Average(params IConverible[] numbers), however that would not be using generics.

C# Unity3D Calculus

I want to use Unity to do math kind of like MATLAB, but also science type things in chemistry, physics, and engineering.
Just wanted to ask if these functions sound right for computing derivatives and partial derivatives numerically, and how I might go about doing 2nd partial derivatives and Laplace operator like in formulas like the Schrodinger's Equation, the Heat Equation, and so on?
I'm still learning Differential Equations, but wanted to relate it to numerical computation in C# for calculation.
public double Derivative(Func<double, double> function, double x, double h)
{
return (function(x + h) - function(x)) / h;
}
public double SecondDerivative(Func<double, double> function, double x, double h)
{
return (function(x + h) - 2 * function(x) + function(x - h)) / (h * h);
}
public double ThirdDerivative(Func<double, double> function, double x, double h)
{
return (function(x + 3 * h) - 3 * function(x + 2 * h) + 3 * function(x + h) - function(x)) / (h * h * h);
}
public double PartialDerivativeX(Func<double, double, double> function, double x, double y, double h)
{
return (function(x + h, y) - function(x, y)) / h;
}
public double PartialDerivativeY(Func<double, double, double> function, double x, double y, double h)
{
return (function(x, y + h) - function(x, y)) / h;
}
You probably have a little way to go.
As a first step, what you should do / must do is
familiarize yourself with all the existing libraries, which approach the challenge you are interested in.
This is the basic pipeline of Unity development (and really all software in our era).
If you search the web, you will find the libraries which handle issues such as derivatives, transcendental functions, etc etc
you could start with this QA, a number of packages are mentioned!
https://stackoverflow.com/a/34208687/294884
By totally familiarizing yourself with existing packages, you will to begin with learn how to package such a thing, API, etc, which is the first thing you have to get comfortable with when you make your own!
Your implementation is a good approximation (since derivative is a limit and h is a finite value). However, I suggest some different code:
public static class MyMath {
// static: we don't want "this"
// Func<double, double> return value: derivative is a function, not a value.
// If we want a point - double - let's name the method as DerivativeAt
// No h - we can't provide correct h for all possible x
public static Func<double, double> Derivative(Func<double, double> function) {
//DONE: Validate public methods arguments
if (null == function)
throw new ArgumentNullException("function");
return new Func<double, double>((x) => {
// Let's compute h for given x
// Easiest, but not the best
double h = Math.Abs(x) < 1e-10 ? 1e-16 : x / 1.0e6;
// "Central" derivative is often a better choice then right one ((f(x + h) - f(x))/h)
return (function(x + h) - function(x - h)) / (2.0 * h);
});
}
// h = 0.0: be nice and let user has no idea what step is reasonable
public static double DerivativeAt(Func<double, double> function,
double x,
double h = 0.0) {
//DONE: Validate public methods arguments
if (null == function)
throw new ArgumentNullException("function");
// If user don't want to provide h, let's compute it
if (0 == h)
h = Math.Abs(x) < 1e-10 ? 1e-16 : x / 1.0e6; // Easiest, but not the best
// "Central" derivative is often a better choice then right one ((f(x + h) - f(x))/h)
return (function(x + h) - function(x - h)) / (2.0 * h);
}
}
If you frequently use Derivative you can try declaring it as an extension method:
public static Func<double, double> Derivative(this Func<double, double> function) {...}
public static double DerivativeAt(this Func<double, double> function,
double x,
double h = 0.0) { ... }
Demo: let's find out maximum error when x within [0 .. 2 * PI) range for Sin function
// We don't want to repeat pesky "MyMath" in "MyMath.Derivative"
using static MyNamespace.MyMath;
...
// Derivative of Sin (expected to be Cos)
var d_sin = Derivative(x => Math.Sin(x));
double maxError = Enumerable
.Range(0, 1000)
.Select(i => 2.0 * Math.PI * i / 1000.0)
.Select(x => Math.Abs(d_sin(x) - Math.Cos(x))) // d(sin(x)) / dx == cos(x)
.Max();
Console.WriteLine(maxError);
Outcome:
1.64271596325705E-10
Edit: "Central" derivative.
As we know, derivative is a limit
df/dx == lim (f(x + h) - f(x)) / h
h -> 0
however we can ask: how h tend to 0. We have a lot of ways in case of complex numbers (h can, say, spiral down to 0 or goes along a strait line); in case of real numbers h can be either positive (right semi-derivative) or negative (left semi-derivative). Usually (standard definition) we require left semi-deivative be equal to right one in order to have derivative:
d+f(x) == d-f(x) == df/dx
However, sometime we use lenient definition ("central" derivative):
df/dx == (d+f(x) + d-f(x)) / 2
For instance, d(abs(x))/dx at x = 0
d-abs(x) = -1
d+abs(x) = 1
d abs(x) / dx doesn't exist (standard definition)
d abs(x) / dx = 0 "central", lenient definition.
Please, note that you current code computes in fact right semi-derivative; in case of Abs(x) you'll get wrong 1. 0 is a better answer in the context if not in calculus but in, say, engineering (imagine a moving car which does have a velocity). Another issue is that when computing derivative at x we don't need f exist at x. For instance
f(x) = x / abs(x) which can be put as
-1 when x < 0
f(x) = doesn't exist when x = 0
+1 when x > 0
Please, note that derivative df/dx at x = 0 exists (it's positive infinity). That's why when computing derivative we should avoid computing f(x). You current code will return
(h / h + 0 / 0) / h == (1 + NaN) / h == NaN
double.NaN - derivative doesn't exists (and that is wrong); "central" derivative will return
(h/h - -h/h) / (2 * h) == 1 / h == some huge number (approximation of +Inf)

Riemann Midpoint Sum getting crazy numbers

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;
}
}

How to calculate the points between two given points and given distance?

I have point A (35.163 , 128.001) and point B (36.573 , 128.707)
I need to calculate the points lies within point A and point B
using the standard distance formula between 2 points, I found D = 266.3
each of the points lies within the line AB (the black point p1, p2, ... p8) are separated with equal distance of d = D / 8 = 33.3
How could I calculate the X and Y for p1 , p2, ... p8?
example of Java or C# language are welcomed
or just point me a formula or method will do.
Thank you.
**The above calculation is actually used to calculate the dummy point for shaded level in my map and working for shaded area interpolation purpose*
that's easy but you need some math knowledge.
PointF pointA, pointB;
var diff_X = pointB.X - pointA.X;
var diff_Y = pointB.Y - pointA.Y;
int pointNum = 8;
var interval_X = diff_X / (pointNum + 1);
var interval_Y = diff_Y / (pointNum + 1);
List<PointF> pointList = new List<PointF>();
for (int i = 1; i <= pointNum; i++)
{
pointList.Add(new PointF(pointA.X + interval_X * i, pointA.Y + interval_Y*i));
}
Straitforward trigonometric solution could be something like that:
// I've used Tupple<Double, Double> to represent a point;
// You, probably have your own type for it
public static IList<Tuple<Double, Double>> SplitLine(
Tuple<Double, Double> a,
Tuple<Double, Double> b,
int count) {
count = count + 1;
Double d = Math.Sqrt((a.Item1 - b.Item1) * (a.Item1 - b.Item1) + (a.Item2 - b.Item2) * (a.Item2 - b.Item2)) / count;
Double fi = Math.Atan2(b.Item2 - a.Item2, b.Item1 - a.Item1);
List<Tuple<Double, Double>> points = new List<Tuple<Double, Double>>(count + 1);
for (int i = 0; i <= count; ++i)
points.Add(new Tuple<Double, Double>(a.Item1 + i * d * Math.Cos(fi), a.Item2 + i * d * Math.Sin(fi)));
return points;
}
...
IList<Tuple<Double, Double>> points = SplitLine(
new Tuple<Double, Double>(35.163, 128.001),
new Tuple<Double, Double>(36.573, 128.707),
8);
Outcome (points):
(35,163, 128,001) // <- Initial point A
(35,3196666666667, 128,079444444444)
(35,4763333333333, 128,157888888889)
(35,633, 128,236333333333)
(35,7896666666667, 128,314777777778)
(35,9463333333333, 128,393222222222)
(36,103, 128,471666666667)
(36,2596666666667, 128,550111111111)
(36,4163333333333, 128,628555555556)
(36,573, 128,707) // <- Final point B
Subtract A from B, component-wise, to get the vector from A to B. Multiply that vector by the desired step value and add it to A. (Note that with eight intermediate steps as you've illustrated, the step distance is 1.0 / 9.0.) Something like this, assuming you really want seven points:
vec2 A = vec2 (35.163, 128.001);
vec2 B = vec2 (36.573, 128.707);
vec2 V = B - A;
for (i = 1; i < 8; i++) {
vec2 p[i] = A + V * (float)i / 8.0;
}
(Sorry, don't know any Java or C#.)
let A be point (xa, ya), and B be point (xb, yb)
alpha = tan-1((yb - ya)/(xb - xa))
p1 = (xa + d * cos(alpha), ya + d * sin(alpha))
pk = (xa + kd * cos(alpha), ya + kd * sin(alpha)), k = 1 to 7
(An equivalent way would be to use vector arithmetic)
At first find the slope of AB line. Get help and formula from here: http://www.purplemath.com/modules/slope.htm
Then consider a triangle of Ap1E(think there is a point E which is right to A and below to p1).
You already know the angle AEp1 is 90degree. and you have calculated angle p1AE(from the slope of AB).
Now find AE and Ep1.
Xp1=Xa+AE and Yp1=Ya+Ep1
This will not be very difficult in C# or java.
Once you understand the logic, you will find pleasure implementing on your own way.

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