Bookmark and Share

Summation Functions

by KodefuGuru 26. July 2010 17:31

Creating a summation function in C# isn’t difficult in itself. After all, it is perfectly reasonable to create functions that consist of more than one line. What is interesting is abstracting it so that any function can become a summation function.

Here is the Madhava-Leibniz function for pi:

Madhava-Leibniz Formula for Pi

Here’s how we can define the inner function:

Func<Int32, Double> f = k =>  4 * (Math.Pow(-1, k) / ((2.0 * k) + 1));

What we want to be able to do is call f.Sum(). This will generate a summation function that calculates pi. Here’s how we accomplish that task.

public static Func<Int32, Double> Sum(this Func<Int32, Double> func, int start = 0)
{
    return end =>
    {
        Double result = default(Double);

        for (int k = start; k <= end; k++)
        {
            result += func(k);
        }

        return result;
    };
}

We need to accumulate the results of every pass into the function. The resulting summation function will still require a parameter representing the upper bound. This is because we actually do need to return at some point in time to inspect the result.

Here’s the test to prove this works.

[TestMethod]
public void Pi()
{
    Func<Int32, Double> f = k =>  4 * (Math.Pow(-1, k) / ((2.0 * k) + 1));
    var calculatePi = f.Sum();
    Assert.AreEqual(3.14159, calculatePi(200000), 7);
}

With 200,000 passes, we can ensure an accuracy of 7. Leibniz didn’t rediscover the most efficient way of calculating pi, but it works for a test of the Sum extension method.

If we switch context to VB, we can even use this with a query expression! A couple of things. 1) VB 10 has a bug and can’t handle the optional parameter… change it to a traditional overload and 2) we need a Cast method.

I’ll let you figure out how to make a traditional overload. The cast method won’t actually do anything (because it will break the function), but we need it because the query expression will try to use it.

public static Func<T, TResult> Cast<TCast, T, TResult>(this Func<T, TResult> func)
{
    return func;
}

Here’s the VB test that uses LINQ!

<TestMethod()>
Public Sub Pi()
    Dim f As Func(Of Integer, Double) = Function(k) 4 * (Math.Pow(-1, k) / ((2.0 * k) + 1))
    Dim calculatePi = Aggregate x In f Into Sum()
    Assert.AreEqual(3.14159, calculatePi(200000), 7)
End Sub

I think it’s easier to just call f.Sum(), but this should give you a taste of where I will be taking things with future articles.

Download the source code from CodePlex!

blog comments powered by Disqus

KodefuGuru.GetInfo()

Chris Eargle
LinkedIn Twitter Technorati Facebook

Chris Eargle
C# MVP, INETA Community Champion


MVP - Visual C#

 

INETA Community Champions
Friend of RedGate
Telerik .NET Ninja
Community blogs & blog posts

I am a #52er

I have joined Anti-IF Campaign


World Map

Tag cloud

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010