<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" version="2.0">

<channel>
	<title>Penned Objects</title>
	
	<link>http://www.pennedobjects.com</link>
	<description>Ideas from the Managed Heap</description>
	<lastBuildDate>Mon, 18 Oct 2010 02:20:48 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/PennedObjects" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="pennedobjects" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Better Rate Limiting in .NET</title>
		<link>http://www.pennedobjects.com/2010/10/better-rate-limiting-with-dot-net/</link>
		<comments>http://www.pennedobjects.com/2010/10/better-rate-limiting-with-dot-net/#comments</comments>
		<pubDate>Mon, 18 Oct 2010 02:20:48 +0000</pubDate>
		<dc:creator>Jack</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[.NET 4.0]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[LINQ]]></category>
		<category><![CDATA[Multithreading]]></category>

		<guid isPermaLink="false">http://www.pennedobjects.com/?p=587</guid>
		<description><![CDATA[Software engineers usually try to make software that does things as quickly as possible. But occasionally we need to limit the rate at which we perform some action. For example, if we&#8217;re building a web crawler, we might rein it in so it doesn&#8217;t overwhelm a server with rapid-fire HTTP requests. Sometimes we can get [...]]]></description>
				<content:encoded><![CDATA[<p></p><p>Software engineers usually try to make software that does things as quickly as possible. But occasionally we need to limit the rate at which we perform some action. For example, if we&#8217;re building a web crawler, we might rein it in so it doesn&#8217;t overwhelm a server with rapid-fire HTTP requests.</p>
<p>Sometimes we can get away with just slowing things down by introducing a delay. Have you ever written code like this?</p>
<pre class="brush: csharp; title: ; notranslate">
for (var i = 0; i &lt; 1000; i++)
{
    PerformAction();
    Thread.Sleep(500);
}
</pre>
<p>A delay between action executions is the simplest form of rate limiting, but it&#8217;s not very precise. The delay time is based on an estimate of how long the action will take to execute. If the action takes less time than estimated, then we might exceed the rate limit. Or if the action takes more time than estimated, then we might limit performance more than we need to. If the action is very complicated, we may not be able to easily estimate how long it will take. And how would this work if the action is being performed in parallel by multiple threads?</p>
<p>If we need a more precise rate control method, then we could try to limit the number of times we execute the action within distinct windows of time. We count the number of executions until we reach the limit, and then we don&#8217;t allow any more until the count is reset to zero at the end of the time window. For example, suppose we&#8217;re aiming for a rate limit of 2 per second. The algorithm would allow only two executions between 0.0 and 1.0 seconds, two more between 1.0 and 2.0 seconds, and so on. This algorithm is effective at controlling the <em>average</em> rate, but it allows for bursts up to two times the rate limit. Using the parameters above, it would allow action executions at 0.8, 0.9, 1.1, and 1.2 seconds, which is 4 occurrences in less than half a second!</p>
<p><img src="http://www.pennedobjects.com/wp-content/uploads/2010/10/Sliding_Window_Rate_Limiting.png" alt="" title="Fixed Windows vs. Sliding Window Rate Limiting" width="366" height="155" class="aligncenter size-full wp-image-621"/></p>
<p>Yet another possible method is to use a rate limiting algorithm like the <a href="http://en.wikipedia.org/wiki/Leaky_bucket">Leaky Bucket</a>. Fortunately these aren&#8217;t terribly difficult to implement. But, like the algorithm above, they&#8217;re really designed for <em>average</em> rate limiting. They usually allow the rate limit to be exceeded for short bursts.</p>
<p>So what would we want of a better rate limiting method? Well, we would want it to limit the number of occurrences N of an action within <em>any</em> time period of length M (i.e. no bursts allowed). It would allow our code to perform as close to the rate limit as possible without exceeding it. And it would be able to enforce the rate limit whether the action is performed in a single thread or by multiple threads in parallel.</p>
<h3>The Rate Limited Pizzeria</h3>
<p>Suppose we&#8217;re in charge of making pizzas at a pizzeria and we have a pizza oven that can hold 6 pizzas at once. The pizza maker assembles the pizzas and then places them in the oven to bake. After each pizza bakes for exactly 30 minutes, another person removes it from the oven, slices it, and boxes it for delivery.</p>
<p>Each pizza that we place in the oven uses one unit of the oven&#8217;s capacity for exactly 30 minutes. It&#8217;s not possible to place more than 6 pizzas in the oven in any 30 minute period. In more academic terms, <em>a system with processing capacity N that processes each item in time M has a maximum processing rate of N/M</em>.</p>
<p>Note that the baking time and oven capacity still limit the rate at which pizzas can be placed in the oven even if more than one pizza maker is making the pizzas. When the oven is full, the pizza makers will have to wait in line to place their pizzas in the oven.</p>
<h3>Building the RateGate</h3>
<p>Using the pizzeria model, if we can create a software object that behaves like the pizza oven and then require that we &#8220;place a pizza in the oven&#8221; before performing an action, then we effectively limit the rate at which we perform the action. We&#8217;ll call this object a RateGate because we&#8217;ll have to &#8220;pass through&#8221; it before we perform the action that we want to rate limit.</p>
<p>Code that requires rate control will configure a RateGate instance, specifying the rate limit by number of occurrences and duration of the time period. Before performing the action, the code will call RateGate.WaitToProceed() which will block the current thread until the action is allowed to occur. Calling WaitToProceed() is like trying to add a pizza to the oven; if the oven is full (i.e. we have hit our rate limit), then the caller will have to wait until a pizza is removed from the oven. For example, the following code calls PerformAction() 1,000 times at a rate of at most 2 times per second:</p>
<pre class="brush: csharp; title: ; notranslate">
// Create a RateGate that allows 2 occurrences per second.
using (var rateGate = new RateGate(2, TimeSpan.FromSeconds(1)))
{
    for (var i = 0; i &lt; 1000; i++)
    {
        rateGate.WaitToProceed();
        PerformAction();
    }
}
</pre>
<p>As you can see, the RateGate is very simple to use. Let&#8217;s take a peek inside to see how it works.</p>
<p>The RateGate contains a <a href="http://en.wikipedia.org/wiki/Semaphore_%28programming%29">counting semaphore</a> that acts like the pizza oven. When a thread calls WaitToProceed(), it will have to wait in line until the semaphore value is less than the count (just like waiting until the number of pizzas in the oven is less than the oven&#8217;s capacity). It can then enter the semaphore (i.e. place a pizza in the oven) and proceed with the action. For our RateGate implementation in .NET 4.0, we&#8217;ll use a <a href="http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.aspx">SemaphoreSlim</a> as our counting semaphore. In previous versions of .NET, we could use a regular old <a href="http://msdn.microsoft.com/en-us/library/system.threading.semaphore.aspx">Semaphore</a>. </p>
<p>At some point we&#8217;ll need to exit the semaphore (i.e. take a pizza out of the oven). Before exiting WaitToProceed(), we compute the time when this should occur and add it to a queue. A queue is convenient because the next semaphore exit time can always be found at the front of the queue.</p>
<p>How do we then exit the semaphore at the time that we computed? We can&#8217;t depend on the thread that entered the semaphore to do it; that thread has moved on to other things like performing the action that we&#8217;re rate limiting. Instead we&#8217;ll take care of this in a separate management thread. Here&#8217;s how it works:</p>
<p><img src="http://www.pennedobjects.com/wp-content/uploads/2010/10/Management_Thread_Flowchart.png" alt="" title="Management Thread Flowchart" width="408" height="472" class="aligncenter size-full wp-image-628" /></p>
<p>We have to ensure that our queue is thread safe because multiple threads may try to add semaphore exit times to the queue concurrently. And the management thread may also be simultaneously removing exit times. In .NET 4.0, we&#8217;ll use a <a href="http://msdn.microsoft.com/en-us/library/dd267265.aspx">ConcurrentQueue&lt;int&gt;</a>, which will handle all of the synchronization internally. In previous versions of .NET, we could use a <a href="http://msdn.microsoft.com/en-us/library/7977ey2c.aspx">Queue&lt;int&gt;</a>, but we would have to implement our own thread synchronization.</p>
<p>The RateGate is obviously very time dependent, so we need to be careful how we measure time. <a href="http://blogs.msdn.com/b/ericlippert/archive/2010/04/08/precision-and-accuracy-of-datetime.aspx">The system clock has a resolution of around 16ms</a>, which should be more than sufficient for general rate limiting; there&#8217;s no need to use a high resolution timer. We could try to use the current system time but we can&#8217;t depend on it to be consistent, even if we avoid daylight saving time by using <a href="http://msdn.microsoft.com/en-us/library/system.datetime.utcnow.aspx">UTC</a>. The system time could still be changed by a user, or it could be adjusted automatically when synchronizing with an external time source. A better clock for our purposes is <a href="http://msdn.microsoft.com/en-us/library/system.environment.tickcount.aspx">System.Environment.TickCount</a>, which gives us the number of milliseconds since the computer started. We just have to be careful because this value is stored as a 32-bit signed integer. The value starts at zero and increases for around 24.9 days until it wraps from Int32.MaxValue (2,147,483,647) to Int32.MinValue (-2,147,483,648). Then it continues increasing until it gets back to Int32.MaxValue. It&#8217;s easy enough to account for this value wrapping by using <a href="http://msdn.microsoft.com/en-us/library/a569z7k8.aspx">unchecked</a> arithmetic to compute differences between time values. The downside is that we won&#8217;t be able to handle any time periods greater than around 49.8 days. But that should be okay; we&#8217;re not really looking to limit the number of occurrences over a period that long.</p>
<p>That covers the general idea behind the RateGate. Please check out the <a href="http://www.pennedobjects.com/wp-content/uploads/2010/10/RateLimiting.zip">source code</a> (.NET 4.0) for additional details. There are plenty of code comments that explain the &#8220;why&#8221; and &#8220;how&#8221;.</p>
<h3>Rate Limiting a Loop</h3>
<p>As a simple example, let&#8217;s use the code above that limits calls to PerformAction() to two per second. We&#8217;ll simulate PerformAction() by sleeping for 250ms and we&#8217;ll record its start and end times. The results with and without rate limiting are below. Notice the delay introduced by the RateGate that keeps the rate below the limit.</p>
<pre class="brush: plain; title: ; notranslate">
Executing 10 times with no rate limiting:
Iteration   Start   Finish
       1       0      249
       2     250      500
       3     500      750
       4     751     1000
       5    1000     1250
       6    1250     1500
       7    1501     1750
       8    1750     2015
       9    2016     2265
      10    2266     2515

Executing 10 times with a rate limit of 2 per second:
Iteration   Start   Finish
       1      17      266
       2     266      516
       3    1012     1262
       4    1273     1523
       5    2022     2272
       6    2287     2537
       7    3036     3286
       8    3301     3551
       9    4050     4300
      10    4315     4565
</pre>
<h3>Rate Limiting LINQ</h3>
<p>Another relatively simple application would be using a RateGate to limit the rate at which a LINQ query is processed through an IEnumerable<T> extension method:</p>
<pre class="brush: csharp; title: ; notranslate">
public static IEnumerable&lt;T&gt; LimitRate&lt;T&gt;(this IEnumerable&lt;T&gt; sequence, int items, TimeSpan timePeriod)
{
    using (var rateGate = new RateGate(items, timePeriod))
    {
        foreach (var item in sequence)
        {
            rateGate.WaitToProceed();
            yield return item;
        }
    }
}
</pre>
<p>We can then use this extension method to limit the rate at which a sequence is enumerated:</p>
<pre class="brush: csharp; title: ; notranslate">
var stopwatch = new Stopwatch();
var sequence = Enumerable.Range(1, 20);
stopwatch.Start();
// Limit the rate of processing the sequence to 5 items per second.
foreach (var number in sequence.LimitRate(5, TimeSpan.FromSeconds(1)))
    Console.WriteLine(&quot;{0,4} {1,6}&quot;, number, stopwatch.ElapsedMilliseconds);
</pre>
<pre class="brush: plain; title: ; notranslate">
Enumerating sequence with rate limit of 5 items per second:
   1     14
   2     33
   3     34
   4     34
   5     34
   6   1026
   7   1029
   8   1029
   9   1029
  10   1029
  11   2040
  12   2040
  13   2040
  14   2040
  15   2040
  16   3058
  17   3058
  18   3058
  19   3058
  20   3059
</pre>
<p>Be careful, though, if using this extension method in a PLINQ query. PLINQ can use a chunking strategy in which it pulls a chunk of items from the sequence before distributing the items for parallel processing. In the code below, suppose PLINQ starts by pulling a chunk of 50 items from the sequence. That part of the processing will be rate limited, taking around 10 seconds to complete. Then PLINQ will start calling PerformAction() for the items that it pulled from the sequence. The calls to PerformAction() will likely be executed in multiple threads, and without any rate limiting at all!</p>
<pre class="brush: csharp; title: ; notranslate">
// Warning: Might not work as expected!
using (var rateGate = new RateGate(5, TimeSpan.FromSeconds(1)))
{
    Enumerable.Range(1, 1000)
        .LimitRate(rateGate)
        .AsParallel()
        .ForAll(x =&gt; PerformAction(x));
}
</pre>
<h3>Rate Limiting and Concurrency</h3>
<p>As a final example, let&#8217;s use a RateGate to rate limit across multiple threads. We&#8217;ll use the Task Parallel Library to execute the rate limited action:</p>
<pre class="brush: csharp; title: ; notranslate">
// Create a RateGate that allows 2 occurrences per second.
using (var rateGate = new RateGate(2, TimeSpan.FromSeconds(1)))
{
    Parallel.For(0, 10, i =&gt;
                            {
                                rateGate.WaitToProceed();
                                PerformAction();
                            });
}
</pre>
<p>The TPL performs the processing out of sequence and introduces some delays, but the RateGate still limits the rate at which the items are processed.</p>
<pre class="brush: plain; title: ; notranslate">
Executing 10 times with no rate limiting:
Iteration   Start   Finish
       1      50      299
       6      61      311
       2      66      316
       3     300      550
       7     317      567
       5     317      567
       4     550      800
       8     567      817
       9     568      817
      10     817     1067

Executing 10 times with a rate limit of 2 per second:
Iteration   Start   Finish
       6       5      255
       1       7      257
       2    1980     2229
       7    1980     2230
       3    2987     3237
      10    2987     3237
       5    4001     4251
       4    4001     4251
       8    5015     5265
       9    5266     5515
</pre>
<h3>Download the Code</h3>
<p>I hope you find the RateGate interesting and/or useful! You can grab the .NET 4.0 source code <a href="http://www.pennedobjects.com/wp-content/uploads/2010/10/RateLimiting.zip">here</a>. Please leave a comment if you have suggestions for improvements or if you find a neat use for it. Cheers!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/PennedObjects?a=b2NNKs1ME0o:ctxKqP7-ZJ0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PennedObjects?d=yIl2AUoC8zA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.pennedobjects.com/2010/10/better-rate-limiting-with-dot-net/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
		<item>
		<title>LINQ Multicasting in .NET 4.0</title>
		<link>http://www.pennedobjects.com/2010/07/linq-multicasting-in-dotnet-4/</link>
		<comments>http://www.pennedobjects.com/2010/07/linq-multicasting-in-dotnet-4/#comments</comments>
		<pubDate>Mon, 12 Jul 2010 15:46:06 +0000</pubDate>
		<dc:creator>Jack</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[.NET 4.0]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[LINQ]]></category>
		<category><![CDATA[Multithreading]]></category>

		<guid isPermaLink="false">http://www.pennedobjects.com/?p=387</guid>
		<description><![CDATA[Why Multicast? SQL Server Integration Services (SSIS) includes a very useful data transformation called &#8220;Multicast&#8221;. If you&#8217;re not familiar with SSIS, it allows you to build (among other things) Data Flow Tasks in which data rows &#8220;flow&#8221; from one or more sources, through one or more transformations, to one or more destinations. For example, you [...]]]></description>
				<content:encoded><![CDATA[<p></p><h3>Why Multicast?</h3>
<p>SQL Server Integration Services (SSIS) includes a very useful data transformation called &#8220;Multicast&#8221;. If you&#8217;re not familiar with SSIS, it allows you to build (among other things) Data Flow Tasks in which data rows &#8220;flow&#8221; from one or more sources, through one or more transformations, to one or more destinations. For example, you could copy rows from one source table to two destination tables by building a Data Flow Task that looks something like this:</p>
<p><img src="http://www.pennedobjects.com/wp-content/uploads/2010/06/SSIS-Multicast.png" alt="" title="SSIS Multicast" width="539" height="133" class="aligncenter size-full wp-image-388" /></p>
<p>The Multicast Transform creates copies of each row it receives from the upstream component and distributes one copy to each downstream component. Multicasting is very important in SSIS because it allows us to avoid executing expensive upstream components multiple times in order to feed the same rows to multiple downstream components.</p>
<p>What if we have a similar situation in .NET? Say we have an IEnumerable&lt;float&gt; and we want to compute the minimum, maximum, and average of all values in the sequence. We could use the Min, Max, and Average standard query operators like this:</p>
<pre class="brush: csharp; title: ; notranslate">
var min = sequence.Min();
var max = sequence.Max();
var average = sequence.Average();
</pre>
<p>But this code will make three separate passes through the sequence to compute the three aggregates. If enumerating the sequence were expensive, then we might not want to do it three times. Wouldn&#8217;t it be great if we had some way to get the same results with only one pass?</p>
<p><a href="http://msmvps.com/blogs/jon_skeet/default.aspx">Jon Skeet</a> and <a href="http://marcgravell.blogspot.com/">Marc Gravell</a> have developed one solution that they call <a href="http://msmvps.com/blogs/jon_skeet/archive/2008/01/04/quot-push-quot-linq-revisited-next-attempt-at-an-explanation.aspx">&#8220;Push&#8221; LINQ</a>. In &#8220;Push&#8221; LINQ, you configure multiple aggregators for use with a single DataProducer object and then tell the DataProducer to &#8220;push&#8221; the elements of the sequence to all of the aggregators. Jon Skeet has also figured out a <a href="http://msmvps.com/blogs/jon_skeet/archive/2010/01/16/first-encounters-with-reactive-extensions.aspx">different solution</a> using the <a href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx">Reactive Extensions for .NET</a>. These are fine solutions, but they require custom-built query operators; you can&#8217;t just use standard query operators.</p>
<h3>Building Multicast in .NET 4.0</h3>
<p>It would be nice to have an IEnumerable&lt;T&gt; extension method that applies multiple aggregators but enumerates the sequence only once. Maybe we could pass the aggregators to this method using lambda expressions and get the results back in a <a href="http://msdn.microsoft.com/en-us/library/system.tuple.aspx">Tuple</a>. Then we could write code like this:</p>
<pre class="brush: csharp; title: ; notranslate">
var tuple = sequence.Multicast(a =&gt; a.Min(), b =&gt; b.Max(), c =&gt; c.Average());
var min = tuple.Item1;
var max = tuple.Item2;
var average = tuple.Item3;
</pre>
<p>The syntax is a bit clumsy, but it&#8217;s workable given the potential performance benefits. Let&#8217;s try to create this extension method for just two aggregators:</p>
<pre class="brush: csharp; title: ; notranslate">
public static Tuple&lt;T1, T2&gt; Multicast&lt;T, T1, T2&gt;(
    this IEnumerable&lt;T&gt; sequence, 
    Func&lt;IEnumerable&lt;T&gt;, T1&gt; aggregator1, 
    Func&lt;IEnumerable&lt;T&gt;, T2&gt; aggregator2)
</pre>
<p>First we have to figure out how the two aggregators can pull from the IEnumerable&lt;T&gt; sequence at the same time. How about running each aggregator in its own thread? We don&#8217;t want to create a lot of threads, but one for each aggregator doesn&#8217;t seem too bad. We&#8217;ll spin up a separate thread for each aggregator and then use a <a href="http://msdn.microsoft.com/en-us/library/system.threading.countdownevent.aspx">System.Threading.CountdownEvent</a> object to block the main thread until the aggregator threads end.</p>
<pre class="brush: csharp; title: ; notranslate">
public static Tuple&lt;T1, T2&gt; Multicast&lt;T, T1, T2&gt;(
    this IEnumerable&lt;T&gt; sequence, 
    Func&lt;IEnumerable&lt;T&gt;, T1&gt; aggregator1, 
    Func&lt;IEnumerable&lt;T&gt;, T2&gt; aggregator2)
{
    // Assign default values for the results.
    var result1 = default(T1);
    var result2 = default(T2);
            
    // Invoke each of the aggregators.
    InvokeAll(new Action[] { () =&gt; result1 = aggregator1.Invoke(sequence),
                             () =&gt; result2 = aggregator2.Invoke(sequence)
                           });

    // Return the aggregator results in a Tuple.
    return new Tuple&lt;T1, T2&gt;(result1, result2);
}

private static void InvokeAll(Action[] actions)
{
    var actionCount = actions.Length;

    // Create the CountdownEvent that will let us wait until all of the
    // action threads end.
    var countdownEvent = new CountdownEvent(actionCount);
            
    // Start the action threads.
    for (var i = 0; i &lt; actionCount; i++)
    {
        // Grab a reference to the current action so we're not accessing a
        // modified closure in the thread delegate below.
        var action = actions[i];

        new Thread(() =&gt;
            {
                // Invoke the action.
                action.Invoke();
                // Signal the CountdownEvent that we're done.
                countdownEvent.Signal();
            }).Start();
    }

    // Wait for the actions threads to end.
    countdownEvent.Wait();
}
</pre>
<p>Within its own thread, each aggregator will call GetEnumerator() on the the IEnumerable&lt;T&gt; sequence and will receive its own instance of the enumerator. Because each aggregator has its own enumerator instance, we&#8217;re still going to be traversing the sequence twice, but now we&#8217;re doing so in parallel. Hmmm, that&#8217;s not much of an improvement. In fact, it&#8217;s could be worse than enumerating the sequence in series. We can take another step in the right direction if both aggregators were to receive the same enumerator instance when they call GetEnumerator(). We can use a custom IEnumerable&lt;T&gt; that wraps the original sequence and have it always give out the same enumerator singleton. Easy enough.</p>
<p>Now suppose that both aggregators get the same enumerator instance when they call GetEnumerator(). Then they&#8217;re going to start iterating the sequence using MoveNext(). We could have some concurrency problems. In one case, the aggregators make alternating calls to MoveNext() and the get_Current() accessor. As a result, each aggregator processes only a subset of the elements of the sequence:</p>
<p><img src="http://www.pennedobjects.com/wp-content/uploads/2010/06/Parallel-Aggregator-Sequence-1.png" alt="" title="Parallel Aggregator Sequence 1" width="331" height="366" class="aligncenter size-full wp-image-410" /></p>
<p>In another case, both aggregators call MoveNext() and then both call get_Current(). The two aggregators will receive the same sequence element, but another element will have been skipped entirely:</p>
<p><img src="http://www.pennedobjects.com/wp-content/uploads/2010/06/Parallel-Aggregator-Sequence-2.png" alt="" title="Parallel Aggregator Sequence 2" width="326" height="366" class="aligncenter size-full wp-image-411" /></p>
<p>We need to ensure that the aggregators each process all of the elements in the sequence, and we can do that by having them iterate the sequence in lockstep. That is, we wait until both aggregators call MoveNext() before actually moving to the next element of the sequence. To accomplish this, we&#8217;ll need a custom IEnumerator&lt;T&gt;, and we&#8217;ll need to somehow make the threads wait until all of the aggregators have called MoveNext(). This is where the new <a href="http://msdn.microsoft.com/en-us/library/system.threading.barrier.aspx">System.Threading.Barrier</a> class in .NET 4.0 comes in.</p>
<p>A Barrier object allows multiple threads to process an algorithm concurrently, but in phases. First we tell Barrier how many threads we have. When each thread completes processing for the current phase, it calls Barrier.SignalAndWait() which blocks the thread until <em>all</em> of the threads have called SignalAndWait(). In our situation, a phase will consist of each aggregate calling MoveNext(), then calling get_Current(), and then processing the item.</p>
<p>We will build an enumerator, LockstepEnumerator&lt;T&gt;, that will use a Barrier object internally. When LockstepEnumerator&lt;T&gt;.MoveNext() is called, it will call Barrier.SignalAndWait(). The Barrier object will wait until all enumerator threads have signaled and then invoke a post-phase delegate which calls MoveNext() on the underlying enumerator. Then LockstepEnumerator&lt;T&gt;.MoveNext() will return the result of the underlying MoveNext() call.</p>
<pre class="brush: csharp; title: ; notranslate">
public class LockstepEnumerator&lt;T&gt; : IEnumerator&lt;T&gt;
{
    private readonly IEnumerator&lt;T&gt; _Enumerator;
    private readonly Barrier _Barrier;
    private bool _MoveNextResult;

    public LockstepEnumerator(IEnumerator&lt;T&gt; enumerator, int degree)
    {
        // Check the arguments.
        if (enumerator == null)
            throw new ArgumentNullException(&quot;enumerator&quot;);
        if (degree &lt;= 0)
            throw new ArgumentOutOfRangeException(&quot;degree&quot;, &quot;Degree must be a positive integer.&quot;);

        _Enumerator = enumerator;

        // Create a Barrier with the given degree as the participant count 
        // and give it a post-phase action that will call MoveNext() on 
        // the enumerator.
        _Barrier = new Barrier(degree, x =&gt; _MoveNextResult = _Enumerator.MoveNext());
    }

    public T Current
    {
        get { return _Enumerator.Current; }
    }

    object IEnumerator.Current
    {
        get { return Current; }
    }

    public void Dispose()
    {
        _Barrier.Dispose();
        _Enumerator.Dispose();
    }

    public bool MoveNext()
    {
        // Signal the Barrier and block the current thread.
        _Barrier.SignalAndWait();

        // The Barrier's post-phase action will have executed before 
        // SignalAndWait unblocks, so return the result of that action 
        // calling MoveNext() on the underlying sequence.
        return _MoveNextResult;
    }

    public void Reset()
    {
        // Doesn't make sense to allow reset with multiple threads 
        // using this enumerator.
        throw new NotSupportedException();
    }    
}
</pre>
<p>The entire sequence for one phase looks like this:</p>
<p><img src="http://www.pennedobjects.com/wp-content/uploads/2010/06/Parallel-Aggregator-Sequence-3.png" alt="" title="Parallel Aggregator Sequence 3" width="546" height="756" class="aligncenter size-full wp-image-412" /></p>
<p>We still need a custom IEnumerable&lt;T&gt; that will hand out a singleton instance of LockstepEnumerator&lt;T&gt; when GetEnumerator() is called. We&#8217;ll call it LockstepEnumerable&lt;T&gt;, and have it wrap the original IEnumerable&lt;T&gt;.</p>
<pre class="brush: csharp; title: ; notranslate">
public class LockstepEnumerable&lt;T&gt; : IEnumerable&lt;T&gt;
{
    // Lazy that will create the enumerator when requested.
    private readonly Lazy&lt;IEnumerator&lt;T&gt;&gt; _Enumerator;

    public LockstepEnumerable(IEnumerable&lt;T&gt; sequence, int degree)
    {
        // Check the arguments.
        if (sequence == null)
            throw new ArgumentNullException(&quot;sequence&quot;);
        if (degree &lt;= 0)
            throw new ArgumentOutOfRangeException(&quot;degree&quot;, &quot;Degree must be a positive integer&quot;);
            
        // Create the Lazy that will create the LockstepEnumerator wrapping 
        // the sequence enumerator.
        _Enumerator = new Lazy&lt;IEnumerator&lt;T&gt;&gt;(() =&gt; new LockstepEnumerator&lt;T&gt;(sequence.GetEnumerator(), degree));
    }

    public IEnumerator&lt;T&gt; GetEnumerator()
    {
        return _Enumerator.Value;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}
</pre>
<p>Finally, we have to modify our Multicast extension method so that it wraps the sequence in a LockstepEnumerable&lt;T&gt;:</p>
<pre class="brush: csharp; title: ; notranslate">
public static Tuple&lt;T1, T2&gt; Multicast&lt;T, T1, T2&gt;(
    this IEnumerable&lt;T&gt; sequence, Func&lt;IEnumerable&lt;T&gt;, T1&gt; aggregator1, 
    Func&lt;IEnumerable&lt;T&gt;, T2&gt; aggregator2)
{
    // Assign default values for the results.
    var result1 = default(T1);
    var result2 = default(T2);

    var multicastSequence = new LockstepEnumerable&lt;T&gt;(sequence, 2);

    InvokeAll(new Action[] { 
                () =&gt; result1 = aggregator1.Invoke(multicastSequence),
                () =&gt; result2 = aggregator2.Invoke(multicastSequence)
            });

    return Tuple.Create(result1, result2);
}
</pre>
<p>And, voil&agrave;! We can multicast.</p>
<h3>Multicast Performance</h3>
<p>Let&#8217;s see our Multicast method in action. To demonstrate its performance characteristics, I started with two sequences: an &#8220;expensive&#8221; sequence and a &#8220;normal&#8221; sequence, each containing 1,000 integers. I simulated &#8220;expensive&#8221; by making the thread sleep for 10ms each time MoveNext() is called. I applied the Min, Max, and Average aggregates to these sequences both with and without Multicast. The mean results for several trials are:</p>
<table cellspacing="0" cellpadding="0" border="0" style="margin-bottom:1em;margin-left:1em;">
<tr>
<td style="padding-right:2em">&#8220;Expensive&#8221; sequence without Multicast:</td>
<td align="right">30,010 ms</td>
</tr>
<tr>
<td style="padding-right:2em">&#8220;Expensive&#8221; sequence with Multicast:</td>
<td align="right">10,036 ms</td>
</tr>
<tr>
<td style="padding-right:2em">&#8220;Normal&#8221; sequence without Multicast:</td>
<td align="right">2 ms</td>
</tr>
<tr>
<td style="padding-right:2em">&#8220;Normal&#8221; sequence with Multicast:</td>
<td align="right">50 ms</td>
</tr>
</table>
<p>The results for the &#8220;expensive&#8221; sequence clearly show the advantages of our Multicast method when applying multiple aggregators. In this scenario, the time saved by making only one pass through the sequence far outweighs the time spent in the aggregators and the overhead of parallel execution. For the &#8220;normal&#8221; sequence, the opposite is true; it&#8217;s far more efficient to make three passes than to incur the overhead of multicasting.</p>
<p>This Multicast extension method isn&#8217;t a silver bullet. It&#8217;s really only good for situations where (1) you&#8217;re applying aggregate query operators to an expensive sequence, (2) you don&#8217;t want to persist the sequence or it would be too expensive to do so, and (3) you don&#8217;t mind spinning up threads. For those situations, though, the performance improvement can be very significant.</p>
<p>You can download a VS.NET project containing code for the Multicast extension method and performance tests <a href='http://www.pennedobjects.com/wp-content/uploads/2010/07/LinqMulticast.zip'>here</a>. The code includes overloads of the Multicast method supporting up to seven aggregators.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/PennedObjects?a=NktBRWYYcQs:x7fCHbRMk1g:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PennedObjects?d=yIl2AUoC8zA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.pennedobjects.com/2010/07/linq-multicasting-in-dotnet-4/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
		<item>
		<title>Adventures in .NET Rounding Part 3: Rounding in Action</title>
		<link>http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-3-rounding-in-action/</link>
		<comments>http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-3-rounding-in-action/#comments</comments>
		<pubDate>Mon, 14 Jun 2010 14:11:39 +0000</pubDate>
		<dc:creator>Jack</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Mathematics]]></category>

		<guid isPermaLink="false">http://www.pennedobjects.com/?p=137</guid>
		<description><![CDATA[This is the third and final post in a series covering rounding in .NET. In Part 1, we learned that the Math.Round method&#8217;s default rounding algorithm probably isn&#8217;t what we would expect, which led to a few more questions about rounding in general. In Part 2, we covered all kinds of different rounding methods and [...]]]></description>
				<content:encoded><![CDATA[<p></p><p>This is the third and final post in a series covering rounding in .NET. In <a href="http://www.pennedobjects.com/2010/05/adventures-in-net-rounding-part-1-the-mystery-of-math-round">Part 1</a>, we learned that the Math.Round method&#8217;s default rounding algorithm probably isn&#8217;t what we would expect, which led to a few more questions about rounding in general. In <a href="http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-2-exotic-rounding-algorithms">Part 2</a>, we covered all kinds of different rounding methods and how they can be implemented in C#. Here in Part 3, we&#8217;ll wrap things up by looking at some specific rounding scenarios and determining which algorithms are most appropriate in those situations.</p>
<p>As before, to remove a bit of complexity, we&#8217;ll assume that &#8220;rounding&#8221; means &#8220;rounding to an integer&#8221;. Once you can round to an integer, it&#8217;s easy to round to arbitrary precision.</p>
<h3>Rounding Individual Values</h3>
<p>The rounding operation simply exchanges a number with an approximation of its value. The difference between that approximation and the original value is called <em>rounding error</em>. Rounding error can be difficult to nail down because it depends on both the fraction part of the number and the rounding method used. Fortunately it&#8217;s fairly straightforward to establish a range and an average for the rounding error when rounding a single value. Then you can often use those results to establish ranges and averages for rounding multiple values.</p>
<p>The table below contains the rounding error ranges and averages for the rounding methods we&#8217;ve been working with. You&#8217;ll notice that I&#8217;ve included specific cases for positive and negative numbers for the Round Toward Zero and Round Away from Zero methods. If you know something about the numbers you&#8217;re rounding, then you can often be more specific about rounding error. For example, suppose you know that a value is the result of dividing an integer by 2 and therefore has a fraction part of 0.0 or 0.5. Then Round Ceiling will always leave the value unchanged or will increase it by exactly 0.5.</p>
<table id="wp-table-reloaded-id-2-no-1" class="wp-table-reloaded wp-table-reloaded-id-2">
<thead>
<tr class="row-1 odd">
<th class="column-1">Rounding Method</th>
<th class="column-2">Rounding Error Range</th>
<th class="column-3">Mean Rounding Error</th>
</tr>
</thead>
<tbody>
<tr class="row-2 even">
<td class="column-1">Round to Nearest (all tie-breaking rules)</td>
<td class="column-2">[-0.5, 0.5]</td>
<td class="column-3">0.0</td>
</tr>
<tr class="row-3 odd">
<td class="column-1">Round Ceiling</td>
<td class="column-2">[0.0, 1.0)</td>
<td class="column-3">0.5</td>
</tr>
<tr class="row-4 even">
<td class="column-1">Round Floor</td>
<td class="column-2">(-1.0, 0.0]</td>
<td class="column-3">-0.5</td>
</tr>
<tr class="row-5 odd">
<td class="column-1">Round Toward Zero</td>
<td class="column-2">In General: (-1.0, 1.0)<br />
Positive Numbers: (-1.0, 0.0]<br />
Negative Numbers: [0.0, 1.0)</td>
<td class="column-3">In General: 0.0<br />
Positive Numbers: -0.5<br />
Negative Numbers: 0.5</td>
</tr>
<tr class="row-6 even">
<td class="column-1">Round Away from Zero</td>
<td class="column-2">In General: (-1.0, 1.0)<br />
Positive Numbers: [0.0, 1.0)<br />
Negative Numbers: (-1.0, 0.0]</td>
<td class="column-3">In General: 0.0<br />
Positive Numbers: 0.5<br />
Negative Numbers: -0.5</td>
</tr>
<tr class="row-7 odd">
<td class="column-1">Round Dither</td>
<td class="column-2">(-1.0, 1.0)</td>
<td class="column-3">0.0</td>
</tr>
</tbody>
</table>
<p>We can reach some useful general conclusions just by examining the rounding error ranges for the various rounding methods. For example, if you&#8217;re looking to minimize the overall rounding error for an arbitrary number, then Round to Nearest is the best choice and you probably want to steer clear of Round Dither. And Round Ceiling will increase the value of an arbitrary number by 0.5 on average and will never decrease the value, so count on it shifting your values toward positive infinity.</p>
<h3>Cumulative Rounding Error</h3>
<p>One of the most famous examples of rounding error is an index that was created in 1982 for the Vancouver Stock Exchange (VSE). The index was assigned a value of 1,000.000 at its inception, but after 22 months the value of the index had fallen to 524.881 with no general downturn in economic activity. Something was wrong. The index value was updated after each stock trade. Rather than recompute the entire index value at each update, the developers who implemented the calculation decided to adjust the value based on the difference in price of the traded stock. After adjusting the index value, they would <em>truncate</em> the result to three decimal places. This truncation caused the index value to lose up to 0.001 points (average 0.0005 points) each time a stock was traded, on average 2,800 times per day. And the rounding error accumulated with every trade. After discovering the error and recomputing the index value (probably using some variation of Round to Nearest), the &#8220;true&#8221; value was found to be 1098.892.</p>
<p>What happened with the VSE index is an example of cumulative rounding error. When rounding is performed after each step of a long running computation, the result has a cumulative error that is the sum of the rounding error at each step.</p>
<p>Let&#8217;s run a simulation of the VSE index with various rounding algorithms. We&#8217;ll start with a value of 1,000.000. At each step, we&#8217;ll adjust the index value by a delta taken from a random Gaussian distribution with mean 0.000 and standard deviation 0.08333, which should reasonably simulate small stock price fluctuations. Then we&#8217;ll run this simulation for 1,232,000 steps (2,800 trades per day x 20 days per month x 22 months). The results are plotted below:</p>
<p><img src="http://www.pennedobjects.com/wp-content/uploads/2010/06/Cumulative-Rounding-Example.png" title="Cumulative Rounding Example" width="550" height="350" class="alignnone size-full wp-image-330" /></p>
<p>The black line represents several overlapping data sets: no rounding, all of the Round to Nearest methods, and Round Dither. There was some variation among the results for these methods, but they performed similarly. The blue line represents Round Ceiling and Round Away from Zero. The green line represents Round Floor and Round Toward Zero. Clearly Round Ceiling, Round Floor, Round Away from Zero, and Round Toward Zero would be poor choices for this scenario. Round Floor and Round Toward Zero are both equivalent to truncation for the values involved in this simulation, and the results are consistent with what happened in real life.</p>
<p>If we were to extend the simulation beyond 22 months, the Round Ceiling and Round Away from Zero values will continue to grow and the Round Floor values will continue toward negative infinity. Once the cumulative result becomes negative, however, Round Toward Zero will tend to drive the value to zero rather than making it more negative. </p>
<p>Because they have an overall mean rounding error of 0.0, Round to Nearest and Round Dither would be reasonable choices for this scenario. Round to Nearest with any tie-breaking rule would probably be the best choice because its rounding error range is smaller. Again, if your data set has properties you can count on, like every pre-rounding value has a fraction part of 0.0 or 0.5, then you&#8217;ll need to pay more attention to this choice.</p>
<h3>Sample Sets</h3>
<p>If we round every value in a set, then we may end up altering characteristics of the set as a whole. We see this in statistical sample sets, where rounding the samples can change the values of statistical measures of the set.</p>
<p>Say we&#8217;re looking at the arithmetic mean of a sample set. If we adjust each value by some &delta;, then the arithmetic mean (&mu;) will also change by exactly &delta;:</p>
<p><img src="http://www.pennedobjects.com/wp-content/uploads/2010/06/Error-Bound-for-Arithmetic-Mean.png" alt="" title="Error Bound for Arithmetic Mean" width="364" height="36" class="aligncenter size-full wp-image-351" /></p>
<p>Suppose we round each value in an arbitrary sample set using Round to Nearest. Each value would change by some &delta; in the range (-0.5, 0.5), which makes the error range for the arithmetic mean (-0.5, 0.5) as well.</p>
<p>Let&#8217;s see an example. We&#8217;ll start with a random Gaussian distribution of 1 million values in the interval [0,100], each with a precision of 1/10. We&#8217;ll apply each of rounding methods to that set. Take a look at this histogram showing some of the results:</p>
<p><img src="http://www.pennedobjects.com/wp-content/uploads/2010/06/Set-Rounding-Histogram.png" alt="" title="Set Rounding Histogram" width="550" height="400" class="aligncenter size-full wp-image-359" /></p>
<p>The rounding methods that are not included are duplicates. Rounding caused values to shift, and that caused variation in the number of samples in each interval. How did it affect our statistical measures?</p>
<table id="wp-table-reloaded-id-4-no-1" class="wp-table-reloaded wp-table-reloaded-id-4">
<thead>
<tr class="row-1 odd">
<th class="column-1"></th>
<th class="column-2">Mean</th>
<th class="column-3">Mean % Change</th>
<th class="column-4">Median</th>
<th class="column-5">Std Dev</th>
<th class="column-6">Std Dev % Change</th>
</tr>
</thead>
<tbody>
<tr class="row-2 even">
<td class="column-1">Unrounded</td>
<td class="column-2">50.004</td>
<td class="column-3"></td>
<td class="column-4">50</td>
<td class="column-5">16.445</td>
<td class="column-6"></td>
</tr>
<tr class="row-3 odd">
<td class="column-1">Round to Nearest, Round Half Away from Zero</td>
<td class="column-2">50.055</td>
<td class="column-3">0.101%</td>
<td class="column-4">50</td>
<td class="column-5">16.445</td>
<td class="column-6">0.017%</td>
</tr>
<tr class="row-4 even">
<td class="column-1">Round to Nearest, Round Half Toward Zero</td>
<td class="column-2">49.954</td>
<td class="column-3">0.100%</td>
<td class="column-4">50</td>
<td class="column-5">16.445</td>
<td class="column-6">0.016%</td>
</tr>
<tr class="row-5 odd">
<td class="column-1">Round to Nearest, Round Half Toward Positive Infinity</td>
<td class="column-2">50.055</td>
<td class="column-3">0.101%</td>
<td class="column-4">50</td>
<td class="column-5">16.445</td>
<td class="column-6">0.017%</td>
</tr>
<tr class="row-6 even">
<td class="column-1">Round to Nearest, Round Half Toward Negative Infinity</td>
<td class="column-2">49.954</td>
<td class="column-3">0.100%</td>
<td class="column-4">50</td>
<td class="column-5">16.445</td>
<td class="column-6">0.016%</td>
</tr>
<tr class="row-7 odd">
<td class="column-1">Round to Nearest, Round Half to Even</td>
<td class="column-2">50.004</td>
<td class="column-3">0.001%</td>
<td class="column-4">50</td>
<td class="column-5">16.446</td>
<td class="column-6">0.018%</td>
</tr>
<tr class="row-8 even">
<td class="column-1">Round to Nearest, Round Half to Odd</td>
<td class="column-2">50.004</td>
<td class="column-3">0.000%</td>
<td class="column-4">50</td>
<td class="column-5">16.445</td>
<td class="column-6">0.017%</td>
</tr>
<tr class="row-9 odd">
<td class="column-1">Round to Nearest, Round Half Randomly</td>
<td class="column-2">50.005</td>
<td class="column-3">0.001%</td>
<td class="column-4">50</td>
<td class="column-5">16.446</td>
<td class="column-6">0.019%</td>
</tr>
<tr class="row-10 even">
<td class="column-1">Round to Nearest, Round Half Alternatingly</td>
<td class="column-2">50.005</td>
<td class="column-3">0.001%</td>
<td class="column-4">50</td>
<td class="column-5">16.446</td>
<td class="column-6">0.018%</td>
</tr>
<tr class="row-11 odd">
<td class="column-1">Round Ceiling</td>
<td class="column-2">50.454</td>
<td class="column-3">0.900%</td>
<td class="column-4">50</td>
<td class="column-5">16.445</td>
<td class="column-6">0.014%</td>
</tr>
<tr class="row-12 even">
<td class="column-1">Round Floor</td>
<td class="column-2">49.554</td>
<td class="column-3">0.900%</td>
<td class="column-4">50</td>
<td class="column-5">16.445</td>
<td class="column-6">0.014%</td>
</tr>
<tr class="row-13 odd">
<td class="column-1">Round Away from Zero</td>
<td class="column-2">50.454</td>
<td class="column-3">0.900%</td>
<td class="column-4">50</td>
<td class="column-5">16.445</td>
<td class="column-6">0.014%</td>
</tr>
<tr class="row-14 even">
<td class="column-1">Round Toward Zero</td>
<td class="column-2">49.554</td>
<td class="column-3">0.900%</td>
<td class="column-4">50</td>
<td class="column-5">16.445</td>
<td class="column-6">0.014%</td>
</tr>
<tr class="row-15 odd">
<td class="column-1">Round Dither</td>
<td class="column-2">50.004</td>
<td class="column-3">0.000%</td>
<td class="column-4">50</td>
<td class="column-5">16.448</td>
<td class="column-6">0.031%</td>
</tr>
</tbody>
</table>
<p>Round Ceiling, Round Floor, Round Away from Zero, and Round Toward Zero are probably unacceptable choices for this scenario. They each changed the mean value of our sample set by nearly 1%, which could have significant impact on any statistical results gleaned from the rounded set. </p>
<p>The Round to Nearest methods performed reasonably well, but there&#8217;s an inherent bias in half of the tie-breaking rules that shows up in the rounded results. Approximately 10% of the values in our random sample set had a fraction part of 0.5 and thus were subject to the tie-breaking rule. Round Half Away from Zero, Round Half Toward Zero, Round Half Toward Positive Infinity, and Round Half Toward Negative Infinity all had a significantly larger effect on the sample set than the other tie-breaking rules.</p>
<p>Round Dither had essentially no effect on the arithmetic mean of the set, but it changed the standard deviation more than any other method.</p>
<p>For the sample set rounding scenario, four rounding methods appear to be superior: Round to Nearest with Round Half to Even, Round to Nearest with Round Half to Odd, Round to Nearest with Round Half Randomly, and Round to Nearest with Round Half Alternatingly. That makes sense because Round to Nearest has the smallest general rounding error range and these tie-breaking rules are designed to eliminate bias.</p>
<h3>Quantization</h3>
<p>Quantization is the process of approximating a continuous range of values (or a very large set of possible discrete values) by a relatively small (usually finite) set of discrete values. This essentially amounts to rounding each sample value to one of the discrete range values. Perhaps the most common use for quantization is in performing analog-to-digital conversion for signals. Audio signals, for instance. The problem is that this process can often change psychometric characteristics of the original signal. Listeners are sensitive to distortion in the signal, so we have to be careful that quantization doesn&#8217;t introduce distortion that they will find unacceptable. We need to apply a method of rounding that preserves the essential characteristics of the signal. Let&#8217;s look at an example of a smooth analog signal quantized using Round to Nearest:</p>
<p><img src="http://www.pennedobjects.com/wp-content/uploads/2010/06/Signal-Quantization-Round-To-Nearest.png" alt="" title="Signal Quantization with Round to Nearest" width="550" height="312" class="aligncenter size-full wp-image-362" /></p>
<p>The approximation looks reasonable, but the stair-step result would sound significantly different than the smoothly increasing curve if this were an audio signal. All of the other rounding methods produce the same kind of stair-step result. Take a look at the results with Round Dither, though:</p>
<p><img src="http://www.pennedobjects.com/wp-content/uploads/2010/06/Signal-Quantization-Round-Dither.png" alt="" title="Signal Quantization with Round Dither" width="550" height="312" class="aligncenter size-full wp-image-363" /></p>
<p>This doesn&#8217;t look all that different from the Round to Nearest stair steps, and it seems like this would be a poor choice with all of those jumps between values. But to the human ear, this is going to sound a lot closer to the original analog signal. For analog signal quantization, Round Dither is the clear choice.</p>
<h3>Conclusion</h3>
<p>We&#8217;ve covered a great deal in this series, but there are other rounding methods and lots of other scenarios to consider. Ultimately you just need to be very careful with rounding. When you round a number, you change its value, and that can have significant effects in your system that can sometimes be difficult to predict. </p>
<p>The best advice is to avoid rounding, or at least round as little as possible. Perform rounding as late as you can in a calculation, and preferably round only the final result. Keep an eye on the context of your problem; look at what values you are rounding and think about the results of rounding those values. Figure out how rounding error will affect your system. And if you care about accuracy, be sure to check your results carefully and impose correctness control (like unit tests) around all critical rounded calculations.</p>
<p>If you&#8217;re interested in the code for the example scenarios (which uses the C# rounding implementations from Part 2), you can download the project <a href='http://www.pennedobjects.com/wp-content/uploads/2010/06/Adventures-in-Rounding.zip'>here</a>. The random Gaussian distributions were easy to generate thanks to Math.NET Iridium, part of the excellent <a href="http://www.mathdotnet.com/">Math.NET Project</a>.</p>
<ul style="margin-bottom:0;">
<li>
            <strong><a href="http://www.pennedobjects.com/2010/05/adventures-in-net-rounding-part-1">Part 1: The Mystery of Math.Round</a></strong><br />
            The Math.Round method isn&#8217;t as straightforward as one might expect.
        </li>
<li>
            <strong><a href="http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-2-exotic-rounding-algorithms">Part 2: Exotic Rounding Algorithms</a></strong><br />
            A menagerie of lesser-known rounding methods, with implementations in C#.
        </li>
<li>
            <strong><a href="http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-3-rounding-in-action">Part 3: Rounding in Action</a></strong><br />
            Why some rounding algorithms are better than others in certain situations.
        </li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/PennedObjects?a=Qt4ELEyXxxY:9LyA9sJgeKQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PennedObjects?d=yIl2AUoC8zA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-3-rounding-in-action/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
		<item>
		<title>Adventures in .NET Rounding Part 2: Exotic Rounding Algorithms</title>
		<link>http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-2-exotic-rounding-algorithms/</link>
		<comments>http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-2-exotic-rounding-algorithms/#comments</comments>
		<pubDate>Mon, 07 Jun 2010 01:26:20 +0000</pubDate>
		<dc:creator>Jack</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Mathematics]]></category>

		<guid isPermaLink="false">http://www.pennedobjects.com/?p=135</guid>
		<description><![CDATA[This is the second in a series of three blog posts covering rounding in .NET. In Part 1, we learned that the Math.Round method&#8217;s default rounding algorithm probably isn&#8217;t what we would expect, which led to many more questions about rounding in general. In Part 2, we&#8217;ll try to answer some of those questions by [...]]]></description>
				<content:encoded><![CDATA[<p></p><p>This is the second in a series of three blog posts covering rounding in .NET. In <a href="http://www.pennedobjects.com/2010/05/adventures-in-net-rounding-part-1-the-mystery-of-math-round/">Part 1</a>, we learned that the Math.Round method&#8217;s default rounding algorithm probably isn&#8217;t what we would expect, which led to many more questions about rounding in general. In Part 2, we&#8217;ll try to answer some of those questions by taking a look at some different rounding methods and how they can be implemented in C#.</p>
<p>For the rest of this discussion, let&#8217;s assume that &#8220;rounding&#8221; means &#8220;rounding to an integer&#8221;. Once you know how to round to an integer, you can round to any precision by multiplying by a factor, rounding to an integer, and then multiplying by the inverse of the factor.</p>
<p>We&#8217;ll break the rounding methods into four groups: Round to Nearest (with its many tie breaking rules), Round Ceiling/Floor, Round Toward Zero/Away from Zero, and Round Dither.</p>
<h3>Round to Nearest</h3>
<p>The most common rounding algorithm, Round to Nearest simply tries to round to the nearest integer value. If the fraction part of the number is less than 0.5, then the result is the next lower integer value. If the fraction part of the number is greater than 0.5, then the result is the next greater integer value. But what if the fraction part of the number is 0.5, equidistant from the two surrounding integers? In that case, we have to apply some kind of tie breaking rule, and there are at least eight rules from which to choose!</p>
<p>The most commonly used tie breaking rule, and rounding method in general, is <strong>Round Half Away from Zero</strong>, also known as Conventional Rounding or Symmetric Arithmetic Rounding. Rounding a fraction part of 0.5 results in <em>the nearest integer that is further from zero</em>. For example, suppose we&#8217;re rounding 1.5. The nearest integers are 1.0 and 2.0, so the result would be 2.0 because it&#8217;s further from zero. Similarly, -1.5 would round to -2.0.</p>
<p>One way to round a positive number with Round Half Away from Zero is to add 0.5 and then truncate the result. To round a negative number, subtract 0.5 and truncate:</p>
<pre class="brush: csharp; title: ; notranslate">
public static int RoundToNearestRoundHalfAwayFromZero(decimal value)
{
    // Add or subtract 0.5 depending on whether the value is positive 
    // or negative, and truncate the result.
    return (int)(value + 0.5m * Math.Sign(value));
}
</pre>
<p>The opposite of Round Half Away from Zero is <strong>Round Half Toward Zero</strong>. This tie breaking rule rounds a fraction part of 0.5 to <em>the nearest integer that is closer to zero</em>. For example, 1.5 would round to 1.0 and -1.5 would round to -1.0.</p>
<p>To round a positive number using this rule, subtract 0.5 and find the next greater integer. To round a negative number, add 0.5 and find the next lower integer:</p>
<pre class="brush: csharp; title: ; notranslate">
public static int RoundToNearestRoundHalfTowardZero(decimal value)
{
    // If value is non-negative, subtract 0.5 and take the next 
    // greater integer. If value is negative, add 0.5 and take the 
    // next lower integer.
    if (value &gt;= 0)
        return (int)Math.Ceiling(value - 0.5m);
    else
        return (int)Math.Floor(value + 0.5m);
}
</pre>
<p>Instead of rounding toward or away from zero, we could round toward positive or negative infinity instead. The <strong>Round Half Toward Positive Infinity</strong> tie breaking rule specifies that we round a fraction part of 0.5 to <em>the next greater integer</em>. For example, 1.5 would round to 2.0 and -1.5 would round to -1.0.</p>
<p>To round to nearest while always rounding a fraction part of 0.5 to the next greater integer, we simply add 0.5 to the number and then find the next lower integer:</p>
<pre class="brush: csharp; title: ; notranslate">
public static int RoundToNearestRoundHalfTowardPositiveInfinity(decimal value)
{
    // Add 0.5 and take the next lower integer.
    return (int)Math.Floor(value + 0.5m);
}
</pre>
<p>The opposite of Round Half Toward Positive Infinity would be the <strong>Round Half Toward Negative Infinity</strong> rule, which instead rounds a fraction part of 0.5 to <em>the next lower integer</em>. For example, 1.5 rounds to 1.0 and -1.5 rounds to -2.0.</p>
<p>To round to nearest while taking a fraction part of 0.5 to the next lower integer, we subtract 0.5 from the number and find the next greater integer:</p>
<pre class="brush: csharp; title: ; notranslate">
public static int RoundToNearestRoundHalfTowardNegativeInfinity(decimal value)
{
    // Subtract 0.5 and take the next greater integer.
    return (int)Math.Ceiling(value - 0.5m);
}
</pre>
<p>Another very common tie breaking rule (and, as we discovered in <a href="http://www.pennedobjects.com/2010/05/adventures-in-net-rounding-part-1-the-mystery-of-math-round/">Part 1</a>, the default for .NET&#8217;s Math.Round method) is <strong>Round Half to Even</strong> or Banker&#8217;s Rounding. As the name suggests,  we round a fraction part of 0.5 to <em>the nearest even integer</em>. For example, 1.5 and 2.5 both round to 2.0 and -1.5 and -2.5 both round to -2.0.</p>
<p>One way to implement Round Half to Even is by first applying Round Half Toward Positive Infinity. If the result is even, we&#8217;re done. Otherwise, we subtract one. If we apply this algorithm to the value 2.5, we first round to 3.0 and then, because 3.0 is not even, we subtract one giving 2.0:</p>
<pre class="brush: csharp; title: ; notranslate">
public static int RoundToNearestRoundHalfToEven(decimal value)
{
    // First round half toward positive infinity. Then if the fraction
    // part of the original value is 0.5 and the result of rounding is
    // odd, then subtract one.
    var temp = (int)Math.Floor(value + 0.5m);
    if (value - Math.Floor(value) == 0.5m &amp;&amp; temp % 2 != 0)
        temp -= 1;
    return temp;
}
</pre>
<p>Why round to the nearest even integer, though? The <strong>Round Half to Odd</strong> rule rounds a fraction part of 0.5 to <em>the nearest odd integer</em> instead. For example, 1.5 rounds to 1.0, 2.5 rounds to 3.0, -1.5 rounds to -1.0, and -2.5 rounds to -3.0. The C# implementation is nearly identical to Round Half to Even:</p>
<pre class="brush: csharp; title: ; notranslate">
public static int RoundToNearestRoundHalfToOdd(decimal value)
{
    // First round half toward positive infinity. Then if the fraction
    // part of the original value is 0.5 and the result of rounding is 
    // even, then subtract one.
    var temp = (int)Math.Floor(value + 0.5m);
    if (value - Math.Floor(value) == 0.5m &amp;&amp; temp % 2 == 0)
        temp -= 1;
    return temp;
}
</pre>
<p>All of the above tie breaking rules have some inherent bias. In order to eliminate the bias, the <strong>Round Half Randomly</strong> rule, also known as Stochastic Rounding, rounds a fraction part of 0.5 <em>to either the next greater or the next lower integer randomly, with equal probability</em>. This method effectively eliminates the bias, but the results are not reproducible (unless a pseudo-random number generator with the same seed value is used as the source of randomness).</p>
<p>To implement Round Half Randomly, we use a random number source to generate a value of either zero or one with equal probability. If the value is zero, we apply the Round Half Toward Positive Infinity rule. If the value is one, we apply the Round Half Toward Negative Infinity Rule:</p>
<pre class="brush: csharp; title: ; notranslate">
private static readonly Random _Random = new Random();

public static int RoundToNearestRoundHalfRandomly(decimal value)
{
    // Randomly use round to nearest with either the round half toward
    // positive infinity or round half toward negative infinity rule.
    if (_Random.Next(0, 2) == 0)
        return (int)Math.Floor(value + 0.5m);
    else
        return (int)Math.Ceiling(value - 0.5m);
}
</pre>
<p>Note that <em>the above code is not thread-safe</em>. In particular, there is a race condition in the Random.Next method that can cause the random sequence to become constantly zero after some point. There are several ways to address this, but perhaps the easiest is to avoid having a System.Random instance that persists between method calls. We could change the method so that it rounds each value in a sequence instead of a single value:</p>
<pre class="brush: csharp; title: ; notranslate">
public static IEnumerable&lt;int&gt; RoundToNearestRoundHalfRandomly(this IEnumerable&lt;decimal&gt; values)
{
    var random = new Random();

    foreach (var value in values)
    {
        // Randomly use round to nearest with either the round half toward
        // positive infinity or round half toward negative infinity rule.
        if (random.Next(0, 2) == 0)
            yield return (int) Math.Floor(value + 0.5m);
        else
            yield return (int) Math.Ceiling(value - 0.5m);
    }
}
</pre>
<p>Like Round Half Randomly, the <strong>Round Half Alternatingly</strong> rule also eliminates bias, but the results are more predictable. We alternate between rounding a fraction part of 0.5 to the next lower and the next greater integer. So, for example, if we had the sequence {1.5, 1.5, 1.5, 1.5}, the result would be {1.0, 2.0, 1.0, 2.0}. </p>
<p>To implement Round Half Alternatingly, we start with a source of alternating sequence of zeros and ones. I&#8217;ve chosen to implement this using an enumerator that provides an infinite alternating sequence:</p>
<pre class="brush: csharp; title: ; notranslate">
private static IEnumerator&lt;int&gt; GetAlternatingEnumerator()
{
    for (; ; ) {
        yield return 0;
        yield return 1;
    }
}
</pre>
<p>Then we can implement the actual rounding method:</p>
<pre class="brush: csharp; title: ; notranslate">
private static readonly IEnumerator&lt;int&gt; _AlternatingSequence = GetAlternatingEnumerator();

public static int RoundToNearestRoundHalfAlternatingly(decimal value)
{
    // Use round to nearest with either the round half toward 
    // positive infinity or the round half toward negative infinity 
    // rule based on the current value of the alternating sequence.
    _AlternatingSequence.MoveNext();
    if (_AlternatingSequence.Current == 0)
        return (int) Math.Floor(value + 0.5m);
    else
        return (int)Math.Ceiling(value - 0.5m);
}
</pre>
<p>Again, there are some thread safety issues because we have to maintain state of the alternating sequence between successive calls to our rounding method. Each thread making calls to this method may not get truly alternating rounding if calls from multiple threads are interleaved. The results would be unpredictable, and could be biased. To get around this, we can again use a method that rounds each value in a sequence rather than just a single value:</p>
<pre class="brush: csharp; title: ; notranslate">
public static IEnumerable&lt;int&gt; RoundToNearestRoundHalfAlternatingly(this IEnumerable&lt;decimal&gt; values)
{
    var alternatingEnumerator = GetAlternatingEnumerator();

    foreach (var value in values)
    {    
        // Use round to nearest with either the round half toward positive
        // infinity or the round half toward negative infinity rule based
        // on the current value of the alternating sequence.
        alternatingEnumerator.MoveNext();
        if (alternatingEnumerator.Current == 0)
            yield return (int)Math.Floor(value + 0.5m);
        else
            yield return (int)Math.Ceiling(value - 0.5m);
    }
}
</pre>
<h3>Round Ceiling and Round Floor</h3>
<p>Sometimes we want to round numbers so that the results are always greater or always lower. At those times, we want to use the Round Ceiling and Round Floor methods. Round Ceiling always rounds a number with a fraction part to <em>the next greater integer</em>. Round Floor always rounds to <em>the next lower integer</em>. These methods are easily implemented using the Math.Ceiling and Math.Floor methods in .NET:</p>
<pre class="brush: csharp; title: ; notranslate">
public static int RoundCeiling (decimal value)
{
    return (int)Math.Ceiling(value);
}

public static int RoundFloor (decimal value)
{
    return (int)Math.Floor(value);
}
</pre>
<h3>Round Toward Zero and Round Away from Zero</h3>
<p>We can pull our values toward zero or push them away from zero, respectively, using the Round Toward Zero and Round Away from Zero rounding methods. As their names suggest, Round Toward Zero rounds every number with a fraction part to <em>the surrounding integer that&#8217;s closer to zero</em>. Round Away from Zero does just the opposite. Round Toward Zero is equivalent to simple truncation, and we can implement the Round Away from Zero method by using either the Round Ceiling or the Round Floor method depending on whether the number is positive or negative.</p>
<pre class="brush: csharp; title: ; notranslate">
public static int RoundTowardZero(decimal value)
{
    // To round toward zero, we can simply truncate by casting to Int32.
    return (int) value;
}

public static int RoundAwayFromZero(decimal value)
{
    return value &gt;= 0 ? (int)Math.Ceiling(value) : (int)Math.Floor(value);
}
</pre>
<h3>Round Dither</h3>
<p>Some instances, such as rounding values in a slowly changing sequence, may call for an approach that maintains the essence of the original sequence and does not result in long sub-sequences that are constant. The Round Dither method achieves this by rounding numbers with fraction parts using either the Round Ceiling or Round Floor method randomly with a probability that is equal to one minus the fraction part. For example, if we round 1.28 to the nearest integer, then it would be rounded to 1.0 with probability 0.72 or rounded to 2.0 with probability 0.28.</p>
<p>To implement Round Dither in C#, we start with a random number source that can generate fractions between 0 and 1. To round a number, we generate a random fraction, and compare it with the fraction part of the number to be rounded. If the random fraction is less than the fraction part of the number, then we use Round Ceiling. Otherwise, we use Round Floor.</p>
<pre class="brush: csharp; title: ; notranslate">
private static readonly Random _Random = new Random();

public static int RoundDither(decimal value)
{
    // If the next random fraction is less than the fraction part of the 
    // number to be rounded, then use Round Ceiling. Otherwise, use 
    // Round Floor.
    if ((decimal)_Random.NextDouble() &lt; Math.Abs(value - (int)value))
        return (int)Math.Ceiling(value);
    else
        return (int)Math.Floor(value);
}
</pre>
<p>As was the case with the implementation of the Round Half Randomly tie-breaking rule above, <em>this code is not thread-safe</em>. Again, one way that we can address this is by creating a method that rounds each value in a sequence rather than just a single value:</p>
<pre class="brush: csharp; title: ; notranslate">
public static IEnumerable&lt;int&gt; RoundDither(this IEnumerable&lt;decimal&gt; values)
{
    var random = new Random();

    foreach (var value in values)
    {
        // If the next random fraction is less than the fraction part of the 
        // number to be rounded, then use Round Ceiling. Otherwise, use 
        // Round Floor.
        if ((decimal)random.NextDouble() &lt; Math.Abs(value - (int)value))
            yield return (int)Math.Ceiling(value);
        else
            yield return (int)Math.Floor(value);
    }
}
</pre>
<h3>Combined Rounding Results</h3>
<p>Before we wrap up, let&#8217;s take a look at how the example numbers from <a href="http://www.pennedobjects.com/2010/05/adventures-in-net-rounding-part-1-the-mystery-of-math-round/">Part 1</a> would be rounded using some of the methods we&#8217;ve seen:</p>
<table id="wp-table-reloaded-id-1-no-1" class="wp-table-reloaded wp-table-reloaded-id-1">
<thead>
<tr class="row-1 odd">
<th class="column-1"></th>
<th class="column-2">-3.5</th>
<th class="column-3">-2.8</th>
<th class="column-4">-2.5</th>
<th class="column-5">-2.2</th>
<th class="column-6">2.2</th>
<th class="column-7">2.5</th>
<th class="column-8">2.8</th>
<th class="column-9">3.5</th>
</tr>
</thead>
<tbody>
<tr class="row-2 even">
<td class="column-1">Round to Nearest, Round Half Away from Zero</td>
<td class="column-2">-4.0</td>
<td class="column-3">-3.0</td>
<td class="column-4">-3.0</td>
<td class="column-5">-2.0</td>
<td class="column-6">2.0</td>
<td class="column-7">3.0</td>
<td class="column-8">3.0</td>
<td class="column-9">4.0</td>
</tr>
<tr class="row-3 odd">
<td class="column-1">Round to Nearest, Round Half Toward Zero</td>
<td class="column-2">-3.0</td>
<td class="column-3">-3.0</td>
<td class="column-4">-2.0</td>
<td class="column-5">-2.0</td>
<td class="column-6">2.0</td>
<td class="column-7">2.0</td>
<td class="column-8">3.0</td>
<td class="column-9">3.0</td>
</tr>
<tr class="row-4 even">
<td class="column-1">Round to Nearest, Round Half Toward Positive Infinity</td>
<td class="column-2">-3.0</td>
<td class="column-3">-3.0</td>
<td class="column-4">-2.0</td>
<td class="column-5">-2.0</td>
<td class="column-6">2.0</td>
<td class="column-7">3.0</td>
<td class="column-8">3.0</td>
<td class="column-9">4.0</td>
</tr>
<tr class="row-5 odd">
<td class="column-1">Round to Nearest, Round Half Toward Negative Infinity</td>
<td class="column-2">-4.0</td>
<td class="column-3">-3.0</td>
<td class="column-4">-3.0</td>
<td class="column-5">-2.0</td>
<td class="column-6">2.0</td>
<td class="column-7">2.0</td>
<td class="column-8">3.0</td>
<td class="column-9">3.0</td>
</tr>
<tr class="row-6 even">
<td class="column-1">Round to Nearest, Round Half to Even</td>
<td class="column-2">-4.0</td>
<td class="column-3">-3.0</td>
<td class="column-4">-2.0</td>
<td class="column-5">-2.0</td>
<td class="column-6">2.0</td>
<td class="column-7">2.0</td>
<td class="column-8">3.0</td>
<td class="column-9">4.0</td>
</tr>
<tr class="row-7 odd">
<td class="column-1">Round to Nearest, Round Half to Odd</td>
<td class="column-2">-3.0</td>
<td class="column-3">-3.0</td>
<td class="column-4">-3.0</td>
<td class="column-5">-2.0</td>
<td class="column-6">2.0</td>
<td class="column-7">3.0</td>
<td class="column-8">3.0</td>
<td class="column-9">3.0</td>
</tr>
<tr class="row-8 even">
<td class="column-1">Round Ceiling</td>
<td class="column-2">-3.0</td>
<td class="column-3">-2.0</td>
<td class="column-4">-2.0</td>
<td class="column-5">-2.0</td>
<td class="column-6">3.0</td>
<td class="column-7">3.0</td>
<td class="column-8">3.0</td>
<td class="column-9">4.0</td>
</tr>
<tr class="row-9 odd">
<td class="column-1">Round Floor</td>
<td class="column-2">-4.0</td>
<td class="column-3">-3.0</td>
<td class="column-4">-3.0</td>
<td class="column-5">-3.0</td>
<td class="column-6">2.0</td>
<td class="column-7">2.0</td>
<td class="column-8">2.0</td>
<td class="column-9">3.0</td>
</tr>
<tr class="row-10 even">
<td class="column-1">Round Toward Zero</td>
<td class="column-2">-3.0</td>
<td class="column-3">-2.0</td>
<td class="column-4">-2.0</td>
<td class="column-5">-2.0</td>
<td class="column-6">2.0</td>
<td class="column-7">2.0</td>
<td class="column-8">2.0</td>
<td class="column-9">3.0</td>
</tr>
<tr class="row-11 odd">
<td class="column-1">Round Away from Zero</td>
<td class="column-2">-4.0</td>
<td class="column-3">-3.0</td>
<td class="column-4">-3.0</td>
<td class="column-5">-3.0</td>
<td class="column-6">3.0</td>
<td class="column-7">3.0</td>
<td class="column-8">3.0</td>
<td class="column-9">4.0</td>
</tr>
</tbody>
</table>
<p>All of the above code is available in a single Rounding static utility class <a href="http://www.pennedobjects.com/wp-content/uploads/2010/06/Rounding-Utility-Class.zip">here</a>. Note that these aren&#8217;t the only possible implementations, or even the most efficient. If you come up with alternate implementations, please post them in the comments.</p>
<p>In Part 2, we have covered most (probably not all) of the algorithms for rounding. Why do we need all of them, though? Can&#8217;t we just pick one? In Part 3, we&#8217;ll learn why it&#8217;s important to use an appropriate algorithm and how you can choose.</p>
<ul style="margin-bottom:0;">
<li>
            <strong><a href="http://www.pennedobjects.com/2010/05/adventures-in-net-rounding-part-1">Part 1: The Mystery of Math.Round</a></strong><br />
            The Math.Round method isn&#8217;t as straightforward as one might expect.
        </li>
<li>
            <strong><a href="http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-2-exotic-rounding-algorithms">Part 2: Exotic Rounding Algorithms</a></strong><br />
            A menagerie of lesser-known rounding methods, with implementations in C#.
        </li>
<li>
            <strong><a href="http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-3-rounding-in-action">Part 3: Rounding in Action</a></strong><br />
            Why some rounding algorithms are better than others in certain situations.
        </li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/PennedObjects?a=Qpq0MT5MWjs:un0KzL6QC2A:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PennedObjects?d=yIl2AUoC8zA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-2-exotic-rounding-algorithms/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
		<item>
		<title>Adventures in .NET Rounding Part 1: The Mystery of Math.Round</title>
		<link>http://www.pennedobjects.com/2010/05/adventures-in-net-rounding-part-1-the-mystery-of-math-round/</link>
		<comments>http://www.pennedobjects.com/2010/05/adventures-in-net-rounding-part-1-the-mystery-of-math-round/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 01:00:29 +0000</pubDate>
		<dc:creator>Jack</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Mathematics]]></category>

		<guid isPermaLink="false">http://www.pennedobjects.com/2010/04/adventures-in-net-rounding-part-1-the-mystery-of-math-round/</guid>
		<description><![CDATA[Rounding seems like a fairly trivial mathematical operation, but I recently discovered that it isn&#8217;t as straightforward as I thought. If you round numbers in .NET, then there&#8217;s a good possibility that you won&#8217;t get the results you expect. This is the first post in a new blog series that will cover how Math.Round rounds, [...]]]></description>
				<content:encoded><![CDATA[<p></p><p>Rounding seems like a fairly trivial mathematical operation, but I recently discovered that it isn&#8217;t as straightforward as I thought. If you round numbers in .NET, then there&#8217;s a good possibility that you won&#8217;t get the results you expect. This is the first post in a new blog series that will cover how Math.Round rounds, some lesser known algorithms (with C# implementations), and how to choose an appropriate algorithm.</p>
<p>Not long ago, I implemented some statistical calculations in C#, and the results weren&#8217;t coming out quite right. I ultimately tracked the problem to where I was rounding using the System.Math.Round method. Take a look at this example:</p>
<pre class="brush: csharp; title: ; notranslate">
var values = new[] { 3.5, 2.8, 2.5, 2.2, -2.2, -2.5, -2.8, -3.5 };

foreach (var value in values)
{
    var roundedValue = Math.Round(value);
    Console.WriteLine(&quot;{0,4:N1} rounds to {1,4:N1}&quot;, value, roundedValue);
}
</pre>
<pre>
 3.5 rounds to  4.0
 2.8 rounds to  3.0
 2.5 rounds to  2.0
 2.2 rounds to  2.0
-2.2 rounds to -2.0
-2.5 rounds to -2.0
-2.8 rounds to -3.0
-3.5 rounds to -4.0
</pre>
<p>Huh?&#8230; 2.5 rounds to 2.0? Shouldn&#8217;t that be 3.0?</p>
<p>I checked the code, checked again, and stared at the screen. “Rounding is so simple,” I thought, “how could .NET get it wrong?” I figured that I should dig into this a bit further, so I opened the .NET Framework Class Library documentation.</p>
<p>The System.Math.Round method has eight overloads. First there are the basic round-to-integer methods:</p>
<pre>
decimal Round(decimal)
double Round(double)
</pre>
<p>Then there are two similar methods that allow rounding to a specified number of decimal places:</p>
<pre>
decimal Round(decimal, Int32)
double Round(double, Int32)
</pre>
<p>Each of the above four methods are duplicated with an additional MidpointRounding parameter:</p>
<pre>
decimal Round(decimal, MidpointRounding)
double Round(double, MidpointRounding)
decimal Round(decimal, Int32, MidpointRounding)
double Round(double, Int32, MidpointRounding)
</pre>
<p>According to the docs, Math.Round always performs a type of rounding called &#8220;round to nearest&#8221;, and the MidpointRounding parameter specifies a tie-breaking rule. This rule specifies how Math.Round should operate on a number that is exactly halfway between two possible rounded values. There are two possible rules: AwayFromZero and ToEven.</p>
<p>MidpointRounding.AwayFromZero specifies that a value halfway between two possible rounded values should always be rounded up. So, for example, 2.5 would round to 3.0. That sounds right. That’s the method that I learned in school. It’s technically known as “symmetric arithmetic rounding” or “round-to-nearest with round-half-away-from-zero tie breaking” (phew).</p>
<p>MidpointRounding.ToEven specifies that a value halfway between two possible rounded values should be rounded toward the nearest <em>even</em> number. So 2.5 would round to 2.0! This method is technically known as “round-to-nearest with round-half-to-even tie breaking” (phew) or “banker’s rounding”.</p>
<p>The four Math.Round overloads without a MidpointRounding parameter default to ToEven rounding, which explains the example above. The .NET team adopted ToEven as the default based on the IEEE Standard for Floating-Point Arithmetic (IEEE 754). With a slight modification to the original code to specify symmetric arithmetic rounding, the results are what I originally expected:</p>
<pre class="brush: csharp; highlight: [5]; title: ; notranslate">
var values = new[] { 3.5, 2.8, 2.5, 2.2, -2.2, -2.5, -2.8, -3.5 };

foreach (var value in values)
{
    var roundedValue = Math.Round(value, MidpointRounding.AwayFromZero);
    Console.WriteLine(&quot;{0,4:N1} rounds to {1,4:N1}&quot;, value, roundedValue);
}
</pre>
<pre>
 3.5 rounds to  4.0
 2.8 rounds to  3.0
 2.5 rounds to  3.0
 2.2 rounds to  2.0
-2.2 rounds to -2.0
-2.5 rounds to -3.0
-2.8 rounds to -3.0
-3.5 rounds to -4.0
</pre>
<p>That solves the original mystery, but there are more questions to answer: Are there any rounding algorithms beyond the two that Math.Round supports? Why would anyone want to use these different algorithms anyway? Why does IEEE Standard 754, section 4 recommend round half to even tie breaking? In Part 2, we’ll look at other types of rounding and how they can be implemented in C#. In Part 3, we’ll learn how to choose an appropriate algorithm.</p>
<ul style="margin-bottom:0;">
<li>
            <strong><a href="http://www.pennedobjects.com/2010/05/adventures-in-net-rounding-part-1">Part 1: The Mystery of Math.Round</a></strong><br />
            The Math.Round method isn&#8217;t as straightforward as one might expect.
        </li>
<li>
            <strong><a href="http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-2-exotic-rounding-algorithms">Part 2: Exotic Rounding Algorithms</a></strong><br />
            A menagerie of lesser-known rounding methods, with implementations in C#.
        </li>
<li>
            <strong><a href="http://www.pennedobjects.com/2010/06/adventures-in-net-rounding-part-3-rounding-in-action">Part 3: Rounding in Action</a></strong><br />
            Why some rounding algorithms are better than others in certain situations.
        </li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/PennedObjects?a=trBkTEGI9DE:8Y9GyePpt7A:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PennedObjects?d=yIl2AUoC8zA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.pennedobjects.com/2010/05/adventures-in-net-rounding-part-1-the-mystery-of-math-round/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/us/</creativeCommons:license>
	</item>
	</channel>
</rss>
