This is what I came up with:
Version 1:
static double Integrate(Func<double, double> f, double low, double high, double delta)
{
return Enumerable.Sum(Enumerable.Select(Enumerable.Range((int)(low / delta), (int)((high / delta) - (low / delta))), c => f(c * delta) * delta));
}
If I'm allowed to use a helper-method it becomes slightly shorter:
Version 2:
static double Integrate(Func<double, double> f, double low, double high, double delta)
{
return Enumerable.Sum(Enumerable.Select(DoubleRange(low, high, delta), c => f(c) * delta));
}
public static IEnumerable<double> DoubleRange(double min, double max, double step)
{
for (double value = min; value <= max; value += step)
{
yield return value;
}
}
Are there any better ways to do this? It's unfortunate LINQ doesn't have an overload for Enumerable.Range that takes floating point values. Are there ways of doing this with either more efficient or less characters of code?
1 Answer 1
Version 1.
It gives incorrect results for some delta
values.
Example: Integrate(x => x * x, 0, 1, 0.1)
gives 0.285
whenever other methods give 0.385
.
Version 2.
Since the delta
is a scalar that is a constant value for the Enumerable.Sum
, it could be moved outside of the Enumerable.Sum
.
Then we can replace the c => f(c) * delta
with a method group f
.
And also we can use Enumerable
's extension methods as extension methods:
static double Integrate(Func<double, double> f, double low, double high, double delta)
{
return delta * DoubleRange(low, high, delta).Sum(f);
}
public static IEnumerable<double> DoubleRange(double min, double max, double step)
{
for (double value = min; value <= max; value += step)
{
yield return value;
}
}
EDIT
The .Select(f).Sum()
was replaced with the .Sum(f)
as @mjolka advised.
-
1\$\begingroup\$ Nice answer! I think you can write
.Sum(f)
instead of.Select(f).Sum()
. \$\endgroup\$mjolka– mjolka2014年11月06日 21:12:02 +00:00Commented Nov 6, 2014 at 21:12
Explore related questions
See similar questions with these tags.