<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Mark Nelson &#187; Mathematics</title>
	<atom:link href="http://marknelson.us/category/mathematics/feed/" rel="self" type="application/rss+xml" />
	<link>http://marknelson.us</link>
	<description>Programming, mostly.</description>
	<lastBuildDate>Fri, 13 Apr 2012 19:25:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>A Big Problem That Doesn&#8217;t Need a Bignum</title>
		<link>http://marknelson.us/2011/02/14/a-big-problem-that-doesnt-need-a-bignum/</link>
		<comments>http://marknelson.us/2011/02/14/a-big-problem-that-doesnt-need-a-bignum/#comments</comments>
		<pubDate>Tue, 15 Feb 2011 00:10:37 +0000</pubDate>
		<dc:creator>Mark Nelson</dc:creator>
				<category><![CDATA[Mathematics]]></category>

		<guid isPermaLink="false">http://marknelson.us/?p=292</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2011/02/14/a-big-problem-that-doesnt-need-a-bignum/' addthis:title='A Big Problem That Doesn&#8217;t Need a Bignum' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>Calculating a probability that involves k-step Fibonacci numbers can be done without resorting to Bignum classes - and the C++ deque container is a perfect class for the job.]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2011/02/14/a-big-problem-that-doesnt-need-a-bignum/' addthis:title='A Big Problem That Doesn&#8217;t Need a Bignum' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><p>When I finally wrapped up the mathematical modeling of the <a href="2011/01/17/20-heads-in-a-row-what-are-the-odds/" class="newpage">k-consecutive heads coin toss problem</a> I had a concise formula:<br />
<center><br />
<img src="/attachments/2011/bignum/Figure7.png"><br />
</center><br />
To calculate the chances of k heads in a row appearing in n tosses, I just had to calculate a k-step Fibonacci number, and then divide it by an exponent of 2, and subtract the result from 1. Not complicated at all &#8211; but there was one catch. After a million coin tosses, the Fibonacci number and the exponent of 2 were approximately 300,000 digits long &#8211; way outside the scope of normal computations in languages like C++ and Java.</p>
<p>To get the exact result I needed, I used the BigInteger and BigDecimal Java classes to handle those big numbers, and had to wait about an hour to get the result. As it turns out, there is a much faster and easier way to do things<br />
<span id="more-292"></span></p>
<h4>Simplifying the Computation</h4>
<p>To solve this problem in a more reasonable matter, take a look at the part of the equation where all the real work is done:<br />
<center><br />
<img src="/attachments/2011/bignum/Figure8.png"><br />
</center><br />
In this equation, the <i>p</i> we are solving for is the probability that <i>no</i> runs of <i>k</i> consecutive heads will occur in <i>n</i> tosses of a fair coin. Although we might be able to find a closed-form equation that defines the k-step Fibonacci number, it is going to be a complicated polynomial, and the chances of us simplifying this equation are effectively nil.</p>
<p>So at first blush I seem to be stuck with calculating the top and bottom parts of the equation independently. But a little inspection of the equation shows that I can actually calculate <i>p</i> in an iterative fashion, starting with <i>n</i>=1, and working my way up to the desired result.</p>
<h4>Calculating the Fibonacci Number</h4>
<p>The first step in the calculation is writing the code to calculate k-step Fibonacci numbers. Recall that the k-step Fibonacci number <i>n</i> is found by summing the values of the previous <i>k</i> numbers &#8211; a recursive definition. The base cases for all values of <i>k</i> are: Fib<sub>k</sub>(n) is 1 when n is 1, and 0 when n is less than 1.</p>
<p>To calculate the value of Fib<sub>k</sub> in an iterative fashion, I make use of the the handy C++ container <code>deque&lt;T&gt;</code>. To calculate a <i>k</i>-step Fibonacci number, I make use of a <code>deque&lt;double&gt;</code> of size <i>k</i> that contains the previous k Fibonacci numbers. With the data structure set up like that, calculating the next Fibonacci number is simple:</p>
<pre>
  q.push_front( accumulate( q.begin(), q.end(), 0 ) );
  q.pop_back();
</pre>
<p>Note that after this calculation, q[ 0 ] contains the next new Fibonacci number, and the previous <i>k-1</i> numbers are still stored in sequence in the <code>deque</code>. The call to <code>pop_back()</code> discards Fib<sub>k</sub>(n-k), which is not going to be needed for the next calculation.</p>
<p>Add the code to initialize the <code>deque</code>, and a loop, and we can print out Fib<sub>k</sub>(n) for values 1 through <i>n</i>:</p>
<pre>
	deque&lt;double&gt; q(k, 0);
	q[0] = 1.0;
	for ( int i = 1 ; i < n ; i++ ) {
            cout << q[ 0 ] << " ";
	    q.push_front( accumulate( q.begin(), q.end(), 0.0 ) );
            q.pop_back();
	}
	cout << q[ 0 ] << endl;
</pre>
<p>Using the familiar value of <i>k</i>=2, and <i>n</i>=20, I get the following output:</p>
<pre>
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
</pre>
<p>The <code>deque</code> is perfect for this class - it lets us simulate a rolling window through the Fibonacci sequence by pushing new values on one end and popping aged ones off the other end. All this while providing constant time access to indexed elements. (Admittedly this code could be written just as efficiently with a <code>list&lt;double&gt;</code>.)</p>
<h4>Divide By Two</h4>
<p>This is a nice simple calculation, but it only gets me halfway to the goal. I'm calculating the top part of the fraction that computes <i>p</i>, but I need to divide by the bottom value as well. As it turns out, I can accomplish this in a way that allows me to iterate to the next value: before I add the values of the previous Fibonacci numbers to <code>q[0]</code>, I just divide all of them by two. The resulting loop ends up looking like this:</p>
<pre>
	deque&lt;double&gt; q(k, 0);
	q[0] = 1.0;
	q[1] = 1.0;
	for ( int i = 1 ; i < n ; i++ ) {
            q.push_front(0.0);
            for ( int j = 1 ; j <= k ; j++ ) {
                q[ j ] /= 2.0;
                q[ 0 ] += q[ j ];
            }
            q.pop_back();
	}
	cout << q[ 0 ] << endl;
</pre>
<p>Note that I've slightly changed the initialization - the <code>deque&lt;double&gt;</code> is initialized with Fib<sub>k</sub>(2) - this is because the top half of the fraction uses Fib<sub>k</sub>(n+2), and the bottom uses 2<sup>n</sup> - the value of n for the Fibonacci calculation always has to be two ahead of the exponent of 2.</p>
<p>This calculation allows me to calculate the probabilities for large numbers of tosses in a matter of seconds, instead of the hour-plus it took using BigInteger. Using this code I was able to get the final word on just when we could be certain that a certain number of coin tosses would produce a run of 20 heads. If we want to be modestly certain, with 90% probability I can say that 4,828,842 coin tosses will produce a run of 20 heads. </p>
<p>If my life depended on it, and I wanted to get out to five nines, I can say that 24,144,137 coin tosses will produce a run of 20 heads with 99.999% probability. The output of <a href="/attachments/2011/bignum/kfib.cpp">kfib.cpp</a> is shown here:</p>
<pre>
There is a 90% probability of seeing 20 consecutive heads in 4828842 tosses of a fair coin
There is a 99% probability of seeing 20 consecutive heads in 9657666 tosses of a fair coin
There is a 99.9% probability of seeing 20 consecutive heads in 14486490 tosses of a fair coin
There is a 99.99% probability of seeing 20 consecutive heads in 19315313 tosses of a fair coin
There is a 99.999% probability of seeing 20 consecutive heads in 24144137 tosses of a fair coin
</pre>
<p>And that's the last thing I am going to say about it.</p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2011/02/14/a-big-problem-that-doesnt-need-a-bignum/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>20 Heads In a Row &#8211; What Are the Odds?</title>
		<link>http://marknelson.us/2011/01/17/20-heads-in-a-row-what-are-the-odds/</link>
		<comments>http://marknelson.us/2011/01/17/20-heads-in-a-row-what-are-the-odds/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 02:44:35 +0000</pubDate>
		<dc:creator>Mark Nelson</dc:creator>
				<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://marknelson.us/?p=187</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2011/01/17/20-heads-in-a-row-what-are-the-odds/' addthis:title='20 Heads In a Row &#8211; What Are the Odds?' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>An exercise in probability demonstrates the exact chances of flipping a fair coin k times in a row given n tosses.]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2011/01/17/20-heads-in-a-row-what-are-the-odds/' addthis:title='20 Heads In a Row &#8211; What Are the Odds?' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><p>A couple of weeks back I <a href="http://marknelson.us/2010/09/12/innumeracy-revisited/" class="newpage">took</a> <a href="http://www.nytimes.com/2010/09/26/magazine/26letters-t-ENGINEERINGT_LETTERS.html" class="newpage">issue</a> with a <a href="http://www.nytimes.com/2010/09/12/magazine/12FOB-IdeaLab-t.html" class="newpage">statement</a> in the New York Times Magazine:</p>
<blockquote><p>
If you have a million coin flips, it’s almost certain that somewhere in those coin flips there will be 20 heads in a row.
</p></blockquote>
<p>My blog post took the Times to task for printing what seemed to be an obviously bogus statement. Since a run of 20 heads is roughly a one-in-a-million occurence, a basic feel for probability should tell you that trying to do this a million times is not going to be a certainty &#8211; fairly far from it.</p>
<p>Naturally, I thought to back up my argument with some hard facts, and I came up with a calculation that showed that the chances of this happening were actually around 60%. Unfortunately, I made a pretty basic mistake in calculating the probability, as was demonstrated to me by correspondent Andy Langowitz. My intuition about the likelihood of success was on the money, but my estimate was a bit high. </p>
<p>The story of how I corrected my error in order to get the correct number, around 37.9%, is a good lesson in careful examination of probability rules, with a small detour into the land of the bignum.<br />
<span id="more-187"></span></p>
<h4>Independent Probabilities</h4>
<p>When trying to develop a formula like this one, it is often easier to work from the inverse. Instead of calculating how likely it is for 20 heads to occur at any point in the sequence of a million tosses, I thought to instead calculate the probability that it wouldn&#8217;t happen. We can then take that number and subtract it from one to get the desired result.</p>
<p>The chance of <i>n</i> heads in a row occurring is 1/2<sup>n</sup>, so the inverse probability is (2<sup>n</sup>-1)/2<sup>n</sup>. If we multiply that probability once for all 999,981 possible occurences of a streak of 20 heads, it seemed to me that I would be in business. Doing this is a simple enough calculation, and the result was the 60% figure. That figure felt like it was in the ballpark to me, and I left it that.</p>
<p>Mr. Langowitz, however, was smart enough to actually test the theory on a smaller set of numbers. Let&#8217;s apply this theory to find out how likely we are to throw two heads in a row in four tries.</p>
<p>The chance of two heads in a row is 1/4, so my formula would give a result of 1 &#8211; (3/4)<sup>3</sup>, or a result of 37/64 &#8211; a little better than 50% chance of it occuring. But probability is nothing but the art of enumerating and counting, and we can do just that to check the result. The 16 equally possible outcome of four tosses are:<br />
<code><br />
HHHH HHHT HHTH HHTT<br />
HTHH HTHT HTTH HTTT<br />
THHH THHT THTH THTT<br />
TTHH TTHT TTTH TTTT<br />
</code><br />
Look through those outcomes and see how many have two consecutive heads. It turns out to be exactly 8, meaning that my calculation of 37/64 is just flat wrong. </p>
<h4>Locating the Mistake</h4>
<p>My mistake is a pretty common one among probability neophytes. I assumed that probability at each step in the sequence was identical, because the sequences were completely independent. It&#8217;s easy enough to think that if you don&#8217;t examine problem carefully. </p>
<p>What actually happens is that when we examine the possibility of an unsuccessful run of heads at toss <i>i</i>, we slightly bias the outcome at toss <i>i+1</i>. A demonstration will show exactly how this happens.</p>
<p>For the sample problem of a sequence of two heads out of four tosses, we can first examine the chance of a negative outcome starting at toss 1. There are just four possible outcomes that have two tosses starting at position 1:<br />
<code><br />
HH HT TH TT<br />
</code><br />
And only one of these tosses yielded two heads in a row, so the probability of not seeing two heads after two tosses is 3/4.</p>
<p>But now when we look at the sequence of tosses starting at position two, we have to throw out the outcomes where we had two heads at toss one &#8211; we&#8217;ve already seen two heads, so we can&#8217;t continue flipping coins in those outcomes. So our universe of possible outcomes is now a bit different:<br />
<code><br />
HTH HTT<br />
THH THT<br />
TTH TTT<br />
</code><br />
Instead of eight outcomes, we have six. And if we look at the first toss seen in position two, instead of having an even distribution of heads and tails, you can see that sample is biased: only two have a head in position two, while four have tails. So the chances of not seeing two heads starting at position two increases to 5/6. Note that this change in probability occurs because we have selected only those outcomes without a streak of two heads at position one.</p>
<p>Likewise, when we look at the possible outcomes for streaks starting at position three, we get a different probability again. Because we have to throw out one sequence in the previous test, the universe of possible outcomes is now limited to:<br />
<code><br />
HTHH HTHT<br />
HTTH HTTT<br />
THTH THTT<br />
TTHH TTHT<br />
TTTH TTTT<br />
</code><br />
So now we have just ten possible outcomes, and  two of those will produce the desired outcome, meaning the probability has changed to 4/5.</p>
<p>So what is the probability of all three possible positions not containing a streak? That would be (3/4)*(5/6)*(4/5) which reduces nicely to 1/2, the correct answer.</p>
<h4>Finding the General Solution</h4>
<p>So let&#8217;s generalize the question at hand: what is the probability of seeing <i>k</i> consecutive heads when a fair coin is tossed <i>n</i> times? The previous section showed that we can work it out by hand for small numbers of tosses, but it should be clear that if are going to toss a coin a million times, the universe of possible outcomes is going to get unwieldy. We need a general description of the problem in order to solve it for any values of <i>k</i> and <i>n</i>.</p>
<p>For many probability problems, finding a solution is simply a way of figuring out how to count things, and coin tosses indeed appear to be just such a problem. Let&#8217;s try to see if we can count the number of times a sequence of <i>k</i> heads will appear at a given toss.</p>
<p>To start to work out the solution to the problem, I will set <i>k</i> to a value of three &#8211; in other words, we will be trying to see what is the probability of seeing three consecutive heads is at toss <i>i</i>,  given that there have not been three heads at an earlier toss.  To calculate the probability, we need to know two things. First, we need to know all the possible outcomes in our universe of samples at toss <i>i</i>.  In the previous section, with a value of <i>k</i>=2, we saw the the number of outcomes for tosses 1, 2, 3, and 4, was 2, 4, 6, and 10.</p>
<p>After determining the number of outcomes, we then need to determine how many of those outcomes were successes. If we defined success as being the number of outcomes in which a <i>k</i> heads in a row appear at position <i>i</i>, the values from the previous section would have been 0, 1, 1, 2.</p>
<h4>Counting the Successes</h4>
<p>I&#8217;ll start with the more difficult problem: counting the number of times <i>k</i> heads appear at toss <i>i</i>.  To start with, we have the degenerate cases where <i>i</i> is less than <i>k</i>. In all of those tosses, we know that the number of successful outcomes is going to be zero, because there have not been enough tosses to achieve success yet.</p>
<p>If we work our way forwards with the example of <i>k</i>=3, our first four tosses end up giving us three sets of outcomes:<br />
<code><br />
H T</p>
<p>HH HT<br />
TH TT</p>
<p>HHH HHT<br />
HTH HTT<br />
THH THT<br />
TTH TTT</p>
<p>HHTH HHTT<br />
HTHH HTHT<br />
HTTH HTTT<br />
THHH THHT<br />
THTH THTT<br />
TTHH TTHT<br />
TTTH TTTT<br />
</code><br />
Note that when we get to toss 3, there is just one successful outcome.  Likewise, in toss 4, there is just one successful outcome.</p>
<p>It may not be immediately obvious, but we can in fact always tell how many successes we will achieve at toss <i>i+k</i> after we have enumerated all the possible outcomes at toss <i>i</i>. The number is defined as the number of outcomes at toss <i>i</i> that end in a tail.</p>
<p>The logic behind this is straightforward: in order to have a success at position <i>i+k</i>, we need to generate a sequence of <i>k</i> heads, starting at toss <i>i+1</i>. If we have an outcome that currently ends in a tail, it will generate 2^<i>k</i> outcomes in the next <i>k</i> tosses, and precisely one and only one of these will have <i>k</i> consecutive heads. None of these outcomes will result in an sequence of <i>k</i> heads before toss <i>i+k</i>, because they currently terminate in a tail, so all of the outcomes generated from that outcome at position <i>i</i> will be included in the outcomes seen at toss <i>i+k</i>.</p>
<p>Likewise, none of the outcomes at position <i>i</i> that currently end in a head are going to be able to contribute to a success at toss <i>i+k</i>. Any streak of <i>k</i> heads that follows a terminating head at toss <i>i</i> will result in a run of <i>k</i> heads <i>before</i> we reach toss <i>i+k</i>.</p>
<p>Looking at our outcomes for <i>k</i>=3, we can see that at toss 1 we have one outcome ending in a tail, so at toss 4 we will have one success. At toss 2 we have two outcomes ending in a tail, so at toss five we will have two successes. And we have the special case of toss 0 &#8211; we have one sequence starting at toss 0 that generates a sequence of <i>k</i> heads at toss <i>k</i>. Although there were no tails tossed at position 0, any sequence that starts there doesn&#8217;t have any preceding heads tosses either, so it is as if there was a single outcome at toss 0 with a value of tails.</p>
<p>So each toss that ends in a tail acts as the root of a successful outcome at a future position. This is good information, but in order to turn this in to a formula we need to be able to compute the number of outcomes ending in tails at toss <i>i</i> &#8211; we don&#8217;t want to have to enumerate all the outcomes in order to get there. I&#8217;ll refer to these special outcomes as <i>anchors</i>, as they form the anchor of a future outcome.</p>
<h4>Counting the Anchors</h4>
<p>The number of anchor outcomes at each position starts out as a nice number while <i>i</i> is less than or equal to <i>k</i>: 2^<i>i</i>. But after toss <i>k</i>, successful outcomes start being removed from the sample set and the formula no longer holds. For <i>k</i>=3, the anchor count starting at toss1 is: 1, 2, 4, 7, 13, 24.</p>
<p>It turns out that the anchor at position <i>i</i> does more than just generate a success at toss <i>i+k</i>. It is also responsible for generating new anchor outcomes at tosses <i>i+1</i>, <i>i+2</i>, &#8230;, <i>i+k-1</i>. </p>
<p>Looking at an example for <i>k=3</i> should clarify this. Our lone anchor outcome at toss 1 is the sequence <code>T</code>. We know that this anchor will create a new successful outcome at toss 4: <code>THHH</code>. But it also creates new anchors at all intermediate tosses: <code>TT</code>, <code>THT</code>, and <code>THHT</code>. </p>
<p>This observation holds true for the generation of all new anchors, and with a little work we can turn this into a usable recurrence. If each anchor at toss <i>i</i> is going to create a new anchor at tosses <i>i+1</i> through <i>i+k-1</i>, we can calculate the number of anchors at toss <i>i</i> using this formula:<br />
<center><br />
<img src="/attachments/2011/tosses/Figure1.png"/><br />
</center><br />
You might recognize this formula if we write it out for <i>k</i>=2:<br/></p>
<p> <code>anchors(i)=anchors(i-1) + anchors(i-2)</code>.</p>
<p>Yes, that is the Fibonacci sequence. For values of k higher than 2, the formula is the <a href="http://mathworld.wolfram.com/Fibonaccin-StepNumber.html" class="newpage">n-step Fibonacci sequence</a>. The well-known Fibonacci sequence recursively adds the previous two values to get the current value. The <b>n-step Fibonacci</b> sequence adds the previous <i>n</i> values in order to get the current value. (For the rest of this article, the n-step Fibonacci number will be referred to as fib<sub>n</sub>(i).)</p>
<p>In the standard Fibonacci recurrence definition, we define a base value of fib(1) = 1, and fib(x) = 0 for all x less than 1. Our anchor count is skewed by one, since our base value at toss 0 is 1. As a result, the the anchor count at toss <i>i</i> is equal to fib<sub>k</sub>(<em>i+1</em>). And from our observation of the link between anchors and successful outcomes, we can then observe that the number of successful outcomes at toss <i>i</i> is equal to fib<sub>k</sub>(<i>i+1-k</i>). </p>
<h4>Counting the Outcomes</h4>
<p>Knowing the number of successful outcomes at toss <i>i</i> only gets us halfway to knowing the actual probability of seeing a sequence of <i>k</i> heads at that point. To get the full probability, we need to know the number of outcomes as well.</p>
<p>Fortunately, this calculation is nearly trivial. In the previous section we saw that the number of anchors at toss <i>i</i> is equal to fib<sub>k</sub>(<em>i+1</em>). Each anchor at toss 1 and greater is simply a sequence of tosses that ends in a tail. And for every sequence ending in a tail, there is a corresponding sequence that is identical except for one key change: it ends in a head instead of a tail. So the number of outcomes at toss <i>i</i> is twice the number of anchors, or 2*fib<sub>k</sub>(<em>i+1</em>).<br />
<center><br />
<img src="/attachments/2011/tosses/Figure2.png"/><br />
</center><br />
Now that we have those numbers, we can finally crank out the probabilities of a streak of <i>k</i> heads appearing at all possible tosses without having to painstakingly enumerate all those sequences of heads and tails. The figure below shows some of the probabilities for tosses starting at 1 for streaks of 2, 3, and 4 heads. It is an excellent exercise to walk through the enumeration process in order to double check the figures &#8211; I encourage you to give it a try.<br />
<center><br />
<img src="/attachments/2011/tosses/Figure3.png"/><br />
</center></p>
<h4>The Absence of a Streak</h4>
<p>Now that we can compute the probability of seeing a streak of <i>k</i> heads at toss <i>i</i>, we need to do just a bit more work to see the what the odds are of seeing that streak at any time in a sequence of <i>n</i> tosses. To get there, we need one more piece of information: the probability of <i>not</i> seeing a streak of <i>k</i> heads at toss <i>i</i> &#8211; in other words, the chances of a negative outcome.</p>
<p>It&#8217;s pretty easy to calculate that number &#8211; simply subtract the number of successful outcomes from the total number of outcomes. The sample sequences for values of <i>k</i> corresponding to 2, 3, and 4 are shown here:<br />
<center><br />
<img src="/attachments/2011/tosses/Figure4.png"/><br />
</center><br />
In order to make the final probability calculation a bit easier, I&#8217;m going to derive a value for the count of failures that simplifies future calculations. In the first line of the figure below we have the basic calculation &#8211; the number of failures at toss <i>i</i> is equal to the total number of outcomes less the number of successes. Both of those two values used to derive the failure count can be expressed in terms of an n-step Fibonacci number, and that is shown on the next line.</p>
<p>In the third line of the figure I simply break out the value first term of the equation into its two component parts. Now, in the next line, I expand the value of fib<sub>k</sub>(<i>i+1</i>) into its component parts, using the definition of the Fibonacci sequence. I keep that grouped in parentheses to make it clear that the new terms are the result of the expansion. Just as an example, if we were doing this expansion for a value of <i>k</i> equal to 3, we would expand fib<sub>3</sub>(<i>i+1</i>) into the sum of fib<sub>3</sub>(<i>i</i>), fib<sub>3</sub>(<i>i-1</i>), and fib<sub>3</sub>(<i>i-2</i>), using the identity of the n-step Fibonacci sequence.</p>
<p>Note that in line 3, the last term of the expanded Fibonacci sequence in parentheses is canceled by the last term overall, which was the number of successful outcomes. When we remove those two elements from the equation, line 5 has simplified into the identity of fib<sub>k</sub>(i+2). So we now have a reasonable number we can use to determine the count of failures at a given toss.<br />
<center><br />
<img src="/attachments/2011/tosses/Figure5.png"/><br />
</center></p>
<h4>Put it All Together</h4>
<p>With all these formulas in hand, we have the tools to determine the final probability we&#8217;ve been working towards: the probability that a sequence of <i>k</i> heads will appear in a sequence of <i>n</i> tosses. To do this, we calculate the cumulative probability that the event does not occur, and subtract that value from 1. The result will be the answer to the question.</p>
<p>The first equation below shows the general approach we take to this problem &#8211; multiplying the probability of failure at each toss. Once we plug in the actual formula for the failure count at each point, and the formula for the total number of outcomes, we see that most of the terms cancel out. We are left with fib<sub>k</sub>(<i>n+2</i>) on top, and 2<sup>n</sup> on the bottom. And that is the final formula that provides an answer to the question.<br />
<center><br />
<img src="/attachments/2011/tosses/Figure6.png"/><br />
</center><br />
Returning to the original supposition in the New York Times, all we need to do is calculate fib<sub>20</sub>(1,000,002) and then divide it by 2<sup>1,000,000</sup>.</p>
<p>Unfortunately, my calculator is not really up to this. Even a desktop calculator that could handle arbitrary precision math won&#8217;t normally have a fib<sub>k</sub> button. </p>
<p>If I had a copy of <a href="http://www.wolfram.com/mathematica/" class="newpage">Mathematica</a>, and knew how to use it, I think I could solve this with just a few lines of input. But I don&#8217;t, so I coded up a short solution in Java.</p>
<p>Java has two classes that enable me to solve this problem in relatively easy fashion: <a href="http://download.oracle.com/javase/1.5.0/docs/api/java/math/BigInteger.html" class="newpage">java.math.BigInteger</a> and <a href="http://download.oracle.com/javase/1.5.0/docs/api/java/math/BigDecimal.html" class="newpage">java.math.BigDecimal</a>. BigInteger performs simple integer calculations with arbitrary precision, and BigDecimal supports floating point math.</p>
<p>My simple app, contained in <a href="/attachments/2011/tosses/Flipper.java" class="newpage">Flipper.java</a>, uses BigInteger to calculate fib<sub>k</sub>(n+2) and 2<sup>n</sup>, then uses BigDecimal to divide the two numbers and subtract the result from 1. Despite fact that the two intermediate results are over 300,000 digits each, the program ran in a very reasonable amount of time, less than an hour. (Optimization of this program would be a very interesting exercise.)</p>
<p>The output of the program is shown here:<br />
<code><br />
fib(20,1000002) = 614579313398524367786474463596 (301000 digits elided)<br />
2^1000000 = 99006562292958982506979236163 (301000 digits elided)<br />
Div = 0.379253961388950068663971868 (999980 digits elided)<br />
</code><br />
So at last, we know the correct result. If you flip a coin a million times, you have a 38% chance of seeing 20 heads in a row. A long way from the certainty claimed by the New York Times, and a bit off from my initial 60% value.</p>
<h4>Postscript</h4>
<p>Working out the details of this problem was a very enjoyable piece of math. When I first started in on the problem, I hoped I would be able to find a reference that simply told me how to calculate the number, but I had no luck. As I worked through the problem, I ran into the existence of the n-step Fibonacci numbers, which I had never heard of. Once I found the reference to them on the Wolfram Alpha page (linked above), I saw that the page had a terse note describing this problem, but with no details. With luck the next person trying to understand this problem will be able to make sense of it by reading this page.</p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2011/01/17/20-heads-in-a-row-what-are-the-odds/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Combinatorial Data Compression</title>
		<link>http://marknelson.us/2011/01/09/combinatorial-data-compression/</link>
		<comments>http://marknelson.us/2011/01/09/combinatorial-data-compression/#comments</comments>
		<pubDate>Sun, 09 Jan 2011 23:10:57 +0000</pubDate>
		<dc:creator>Mark Nelson</dc:creator>
				<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Data Compression]]></category>
		<category><![CDATA[Mathematics]]></category>

		<guid isPermaLink="false">http://marknelson.us/?p=154</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2011/01/09/combinatorial-data-compression/' addthis:title='Combinatorial Data Compression' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>Newcomers to the world of data compression often stumble on this old idea in hopes of creating a novel and powerful algorithm. In a nutshell, the idea is to create an enumerative coding system that uses combinatorial numbering to identify a message, in hopes of providing a more compact representation . Unfortunately, these schemes always [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2011/01/09/combinatorial-data-compression/' addthis:title='Combinatorial Data Compression' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><p>Newcomers to the world of data compression often stumble on this old idea in hopes of creating a novel and powerful algorithm. In a nutshell, the idea is to create an enumerative coding system that uses combinatorial numbering to identify a message, in hopes of providing a more compact representation . Unfortunately, these schemes always fail, for reasons that I&#8217;ll lay out in this article.<br />
<span id="more-154"></span></p>
<h4>Combinations</h4>
<p>To design a combinatorial algorithm that will compress files, you can think of the file as a series of integers. Since most of the files that you use are streams of bytes, consider each file to be a sequence of integers with values from 0 to 255.</p>
<p>If you go back to your first classes on probability and statistics, you might remember the definition of a <a href="http://en.wikipedia.org/wiki/Combination" class="newpage">combination</a>. A combination is simply a way of selecting a number of things from a larger set. When you are trying to compress a file of bytes, the natural size of this set is 256.</p>
<p>Probability theory tells us that we can count the number of combinations of a given size using a pretty simple formula. If a set has <em>n</em> elements and we are choosing <em>k</em> at a time, the number of possible combinations is given by the formula n!/k!*(n-k)!. This number is also known as the <em>binomial coefficient</em>.</p>
<p>Just for a simple example, the number of different ways you can select three bytes out of a set of 256 is 2,763,520. In general, with a large set, most combinations are going to generate very large numbers. The exceptions will be for values of k that are either very small or very close to the size of the set.</p>
<p>Combinations are well ordered, so any instance of the three bytes has a specific number between 0 and 2,763,519. We can call this the combinatorial rank. This means I can identify any three byte sequence by a combination number.</p>
<p>Assuming all combinations are equal, we can use an optimal arithmetic coder to encode this number in lg(2,763,510) bits, roughly 21.4. That&#8217;s interesting, because the three bytes actually take up 24 bits, so maybe there is some savings to be found here.</p>
<h4>The First Problem</h4>
<p>Knowing the combinatorial rank is good, but it won&#8217;t let you reconstruct a compressed file on its own. The combinatorial rank gives you the set of bytes in the file, but doesn&#8217;t tell you the <i>order</i> of those bytes. If there are k bytes, they can be ordered in k! different permutations. So to fully describe the file, you need to encode the combination rank <em>and</em> the permutation number.</p>
<p>Encoding the permutation for your 3 byte file is going to take 2.58 bits, calculated as lg(3!). This makes the total needed to encode your three byte file 23.98 bits. Admittedly not a lot of savings, but it&#8217;s also non-zero.</p>
<p>Let&#8217;s look at the number of bits needed to encode a 20 byte message. The number of combinations of this length are roughly 2.8*10^29, which will take 97.8 bits to encode. 20! is roughly 2.43*10^18, which will take 61.1 bits to encode. The total comes out to 158.9 bits. Since we&#8217;re encoding 160 bits of information, there is clearly a greater savings.</p>
<p>As the message size increases, the savings start to grow. At a message length of 50 we save 7.5 bytes, at 75 bytes we save 16 bytes per message. The trend looks good. By the time you get to a message length of 100 bytes, you&#8217;re saving 32 bits per message &#8211; a compression of 4% for doing nothing but recoding!</p>
<h4>The Second Problem</h4>
<p>The second problem you encounter in the combinatorial system is that, by definition, a combination is composed of unique elements. So if you are compressing a three byte file, you can&#8217;t have any duplicate bytes. Is this a problem?</p>
<p>Your inclination is to hope not. You know that every compression scheme only works on a subset of files, so perhaps the combinatorial scheme can be developed to work on segments of files with no duplicates. </p>
<p>How likely are you to find a duplicate in a file of three bytes? You can start by enumerating the total number of files of that length: 256^3. And you know how many files there are with no duplicates: the combinatorial number times the number of permutations. So it&#8217;s a simple matter to calculate the probability that a message of length k has no duplicated bytes. The value will be n!/(n-k)!*256^k.</p>
<p>For a value of 3, we see that the probability of no duplicate bytes is .988 &#8211; this means you can compress almost every file by a fraction of a bit.</p>
<p>You&#8217;d like to think that you can look at pretty long stretches of data and expect a low probability of duplicates, but unfortunately you run into the <a href="http://en.wikipedia.org/wiki/Birthday_problem" class="newpage">Birthday Paradox</a>. In the birthday paradox, you&#8217;re asked a question something like this: in a room of 23 people, what are the chances that two people share a common birthday? For most people, the answer, 50% or so, is non-intuitive. </p>
<p>Likewise, it means that a file with 100 bytes and no duplicates is such a rarity that it might as well never appear &#8211; the chances are less than one in a billion.</p>
<h4>Facing the Music</h4>
<p>You can see the problem here. We can compress very short sequences using a combinatorial system, but the savings are very small. Even so, we can compress most files. We can compress longer files for greater savings, but very few sequences will prove to be eligible.</p>
<p>It&#8217;s actually worse than that. Let&#8217;s work out the number on a hypothetical compressor. This compressor will use a combinatorial scheme to compress all files of 10 bytes. The compressor will look at the file, and if it has no duplicates, it will set a flag symbol in the output stream to be true, followed by the combinatorial number, followed by the permutation.</p>
<p>If the 10 byte file has duplicates, the compressor will generate a flag symbol of false, followed by the uncompressed data.</p>
<p>If this scheme gives us some savings, we can scale it up to operate on files of any size &#8211; we&#8217;ll just compress them in 10-byte chunks.</p>
<p>So let&#8217;s analyze the result. First, the number of files that will make it past the first test is pretty impressive: 83.695%. Each of these files will be compressed down to 79.743 bits. The remaining 16.305 percent will take exactly 80 bits in the output stream. So the overall size of our output file thus far is going to add up to 79.78519 bytes. Our algorithm is still in the black!</p>
<p>Unfortunately, we also need to account for the cost of the flag message. Using optimal coding, when the flag is true we are going to require .25679 bits. When it is false, optimal coding of the much rarer message will require 2.6 bits. Add in the cost of the flag, and the average output size goes up to a smidgen over 80 bits. </p>
<p>In other words, you lose.</p>
<h4>Conclusion</h4>
<p>The problem is a familiar one in data compression. Every time you come up with a way to encode a subset of files that saves some space, you find that all your savings are lost when you try to encode the files that aren&#8217;t part of the subset. Even using a single bit to flag special files as being incompressible is enough to wipe out your savings. It is the definition of <a href="http://www.amazon.com/Hasbro-40509-Whac-A-Mole-Game/dp/B0001GDP00?tag=theinternetdatac" class="newpage">Whac-A-Mole</a>.</p>
<p>With combinatorial coding you will find that same rule to hold true as for all forms of data compression: It isn&#8217;t going to be a universal compressor that can reduce every file in size. The only reason it will be useful is if you have an input set of files that all have a common characteristic: a preponderance of streams where duplicates are rare. And odds are, this set of files will probably be compressible using some more reasonable algorithm.</p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2011/01/09/combinatorial-data-compression/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Innumeracy Revisited</title>
		<link>http://marknelson.us/2010/09/12/innumeracy-revisited/</link>
		<comments>http://marknelson.us/2010/09/12/innumeracy-revisited/#comments</comments>
		<pubDate>Sun, 12 Sep 2010 17:35:39 +0000</pubDate>
		<dc:creator>Mark Nelson</dc:creator>
				<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Culture]]></category>
		<category><![CDATA[Humor]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Snarkiness]]></category>

		<guid isPermaLink="false">http://marknelson.us/2010/09/12/innumeracy-revisited/</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2010/09/12/innumeracy-revisited/' addthis:title='Innumeracy Revisited' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>The New York Times has an interesting article today examining the curious fact that certain types of terrorist organizations have an unusually high ratio of engineers among their members. An interesting point to study, no doubt, but what caught my eye was this little blunder: William A. Wulf, a former president of the National Academy [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2010/09/12/innumeracy-revisited/' addthis:title='Innumeracy Revisited' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><p>The New York Times has an interesting <a href="http://www.nytimes.com/2010/09/12/magazine/12FOB-IdeaLab-t.html" class="newpage">article</a> today examining the curious fact that certain types of terrorist organizations have an unusually high ratio of engineers among their members. An interesting point to study, no doubt, but what caught my eye was this little blunder:</p>
<blockquote><p>
William A. Wulf, a former president of the National Academy of Engineering, is, no surprise, no fan of the Gambetta-Hertog theory. “If you have a million coin flips,” he says, “it’s almost certain that somewhere in those coin flips there will be 20 heads in a row.”
</p></blockquote>
<p>This numerical gaffe is a prime example of innumeracy, a <a href="http://marknelson.us/2008/07/20/innumeracy-part-n/" class="newpage">favorite</a> <a href="http://www.drdobbs.com/blog/archives/2008/05/innumeracy_cont.html" class="newpage">topic</a> of mine, and it is doubly bad. First, the New York Times with its old-school print-format hubris regarding fact checking should not have let this slip by unnoticed. Second, the fact that the speaker is not just an engineer, but president of our National Academy, adds insult to injury.<br />
<span id="more-132"></span></p>
<h3>Probability 101</h3>
<p>The Wikipedia says that <a href=http://en.wikipedia.org/wiki/Numeracy" class="newpage">Numeracy</a> is <i>the ability to reason with numbers and other mathematical concepts.</i> In today&#8217;s world, it should be considered as important as literacy. So let&#8217;s try doing some thinking about this problem.</p>
<p>What should first catch your eye in this is the meaning behind &#8220;20 heads in a row.&#8221; As a programmer, you are instinctively aware that 2 to the 20th power is roughly one million. This means that the chances of flipping a true coin and having it land heads up 20 times in a row is inded roughly one in a million. Does this mean that flipping a coin a million times renders such a streak &#8220;almost certain?&#8221; Of course not.</p>
<p>If the chance of flipping a single head is one in two, and I flip a coin two times, am I almost certain to see one head? No. If the chances of two heads in a row is one in four, am I almost certain to see a streak of two if I flip four times? Still we intuitively answer no. It seems likely, but nowhere near a certainty. So the task in front of us is to scale this equation up and see if it changes in character as we near one million.</p>
<h3>Pinning it Down</h3>
<p>Determining how likely this streak is requires a frequent ruse we employ in probability. Instead of calculating the probability directly, we determine out how likely it is <i>not to occur</i>, then subtract that value from one.</p>
<p>We know that the chance of the coin flip happening in the first 20 flips is 1/2^20. We&#8217;ll call this number <i>p</i>. Now let&#8217;s imagine a sequence of a million coin flips. The chance of a streak of 20 heads not starting at position one is 1-<i>p</i>. The chance of it not happening in the sequence of coins starting at position 2 is likewise 1-<i>p</i>. The same probability is true for every sequence of flips from position 1 to position 999,981, the last possible start of a streak of twenty.</p>
<p>The chances of not seeing a coin flip in every one of those positions is found by multiplying each of their values, leading to the rather unwieldy formula (1-<i>p</i>)^999,981. Unwieldy, perhaps, but your scientific calculator will quickly tell you it resolves to roughly 0.39. So the chances of seeing 20 heads in a row after a million coin flips is more or less 61%. Hardly &#8220;almost certain&#8221;.</p>
<h3>Finding Almost Certain</h3>
<p>I&#8217;d like to think that &#8220;almost certain&#8221; is somewhere in the neighborhood of 99%. I&#8217;ll leave the calculation as an exercise for the reader, but if your calculator has a log button you will be able to determine that you will need almost five million coin tosses to achieve near certainty. And when you think about it (using your beloved numeracy) that number seems a lot more realistic. Something that has a one in a million chance of occuring would seem to be only somewhat likely to occur in a million tries. Give me five million and it&#8217;s a sure thing.</p>
<p>Ironically, the <a href="http://en.wikipedia.org/wiki/The_New_York_Times" class="newpage">Gray Lady</a> just ran an <a href="http://www.nytimes.com/2010/08/22/magazine/22FOB-medium-t.html" class="newpage">ode to fact checking</a> a few weeks ago. Apparently that department is short on people with any sort of mathematical fluency. Perhaps they should think about hiring an engineer or two?</p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2010/09/12/innumeracy-revisited/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>P ≠ NP?</title>
		<link>http://marknelson.us/2010/08/10/p-%e2%89%a0-np/</link>
		<comments>http://marknelson.us/2010/08/10/p-%e2%89%a0-np/#comments</comments>
		<pubDate>Tue, 10 Aug 2010 18:42:47 +0000</pubDate>
		<dc:creator>Mark Nelson</dc:creator>
				<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[People]]></category>

		<guid isPermaLink="false">http://marknelson.us/2010/08/10/p-%e2%89%a0-np/</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2010/08/10/p-%e2%89%a0-np/' addthis:title='P ≠ NP?' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>You may have never heard of Vinay Deolalikar, but there is a chance that he may become next year&#8217;s Turing Award winner, not to mention an overnight millionaire. It seems that Vinay dropped the news at the start of this week that he had proven that P does not equal NP. In short, this proof [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2010/08/10/p-%e2%89%a0-np/' addthis:title='P ≠ NP?' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><p>You may have never heard of <a href="http://www.hpl.hp.com/personal/Vinay_Deolalikar/">Vinay Deolalikar</a>, but there is a chance that he may become next year&#8217;s <a href="http://awards.acm.org/homepage.cfm?awd=140">Turing Award</a> winner, not to mention an overnight <a href="http://www.claymath.org/millennium/P_vs_NP/">millionaire</a>. It seems that Vinay dropped the news at the start of this week that he had proven that P does not equal NP. In short, this proof means that many problems we suspect are hard to solve are in fact provably hard to solve. Whether his proof succeeds or not, the Interwebs are abuzz with the news.<br />
<span id="more-129"></span><br />
<a href="http://en.wikipedia.org/wiki/P_versus_NP_problem">P versus NP</a> is arguably the biggest unanswered problem in Computer Science, and proving it one way or another will cascade into new results and conclusions in many areas of computing and mathematics. The problem is at least 40 years old, and despite people literally devoting their entire careers to the problem, has yet to be decided. Some researchers suspect it can&#8217;t be proved, although this has not been proven either.</p>
<p>When a famous problem like this has been stewing for so long, it is not unusual to see sporadic cries of proof, but these need to be taken with a grain of salt. The first test is to see if the person is a flake with a proof that won&#8217;t survive a casual scan. Passing that test, the proof then has to endure the normal peer review process. Proofs that plumb difficult new ground can take years to be accepted.</p>
<p>It appears that Deolalikar has passed the first test &#8211; people are seriously studying his proof. However, given its complexity and length, you can expect that general acceptance will not happen overnight. More likely, specific problems will arise, challenges will be published, and Deolalikar will either respond, modify his proof, or retreat for more study. If he indeed has the golden ticket, he will be cashing a million dollar prize from the Clay Mathematics Institute sometime soon.</p>
<p>It&#8217;s remarkable news indeed, and perhaps the only way it would have been more remarkable would have been with a proof that P equals NP.</p>
<p>Feel like weighing in? Check out the <a href="http://www.hpl.hp.com/personal/Vinay_Deolalikar/Papers/pnp12pt.pdf">proof</a> yourself and see what you think.</p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2010/08/10/p-%e2%89%a0-np/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>5 Trillion Digits of Pi</title>
		<link>http://marknelson.us/2010/08/06/5-trillion-digits-of-pi/</link>
		<comments>http://marknelson.us/2010/08/06/5-trillion-digits-of-pi/#comments</comments>
		<pubDate>Fri, 06 Aug 2010 18:46:27 +0000</pubDate>
		<dc:creator>Mark Nelson</dc:creator>
				<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Mathematics]]></category>

		<guid isPermaLink="false">http://marknelson.us/2010/08/06/5-trillion-digits-of-pi/</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2010/08/06/5-trillion-digits-of-pi/' addthis:title='5 Trillion Digits of Pi' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>Back in 1981, fresh out of school, I was awestruck by Steve Wozniak&#8217;s program that calculated over 100,000 digits of e on an Apple II. (Anyone who has a scan of his article in the June 1981 issue of Byte, please email me a copy!) Shortly after reading the article, I ported his program to [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2010/08/06/5-trillion-digits-of-pi/' addthis:title='5 Trillion Digits of Pi' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><p>Back in 1981, fresh out of school, I was awestruck by Steve Wozniak&#8217;s program that calculated over 100,000 digits of e on an Apple II. (Anyone who has a scan of his article in the June 1981 issue of Byte, please email me a copy!) Shortly after reading the article, I ported his program to the PDP-11 at my office and duplicated his results, down to the last digit.</p>
<p>These days the stakes are much higher when it comes to calculating the values of constants. Alexander Yee and Shigeru Kondo have just <a href="http://www.numberworld.org/misc_runs/pi-5t/details.html">announced</a> the calculation of pi to 5 trillion digits. And oddly enough, this was accomplished on a desktop machine running Windows server, not the Linux cluster I would have expected.</p>
<p>Here are some of key stats:</p>
<dl>
<dt>Operating System</dt>
<dd>Windows Server 2008 R2 Enterprise x64<//dd></p>
<dt>Software</dt>
<dd><a href="http://www.numberworld.org/y-cruncher/">y-cruncher</a></dd>
<dt>Processor</dt>
<dd>2 Intel Xeon X5680 @3.33 GHz offering 24 hyperthreaded processors</dd>
<dt>Disk Space</dt>
<dd>The computation required roughly 22TB of disk space, and the compressed result takes another 3.8TB</dd>
<dt>Time</b></dt>
<dd>The task took 90 days to complete, and 66 hours to verify</dd>
</dl>
<p>The y-cruncher software package that broke this record also holds records for several other constants, including one trillion digits of e. So in 30 years, more or less, the desktop PC has gone from constant calculations under a million digits to over a trillion digits. That growth rate of 1.7x per year maps pretty well to <a href="http://en.wikipedia.org/wiki/Moore's_law">Moore&#8217;s Law</a>, suggesting that we can expect these numbers to continue climbing for at least a few more years.</p>
<p>Kudos to Alexander Yee and Shigeru Kondo on a smashing accomplishment!</p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2010/08/06/5-trillion-digits-of-pi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Innumeracy Part N</title>
		<link>http://marknelson.us/2008/07/20/innumeracy-part-n/</link>
		<comments>http://marknelson.us/2008/07/20/innumeracy-part-n/#comments</comments>
		<pubDate>Sun, 20 Jul 2008 19:56:27 +0000</pubDate>
		<dc:creator>Mark Nelson</dc:creator>
				<category><![CDATA[Complaining]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Snarkiness]]></category>

		<guid isPermaLink="false">http://marknelson.us/2008/07/20/innumeracy-part-n/</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2008/07/20/innumeracy-part-n/' addthis:title='Innumeracy Part N' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>This isn&#8217;t the first time I&#8217;ve complained about innumeracy, and I&#8217;m sure it won&#8217;t be the last. Just to get off on the right foot, let me give the definition of the word from thesite innumeracy.com: A term meant to convey a person&#8217;s inability to make sense of the numbers that run their lives. Innumeracy [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2008/07/20/innumeracy-part-n/' addthis:title='Innumeracy Part N' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><p>This isn&#8217;t the first time I&#8217;ve <a href="http://www.drdobbs.com/blog/archives/2008/05/innumeracy_cont.html" class="newpage">complained about innumeracy</a>, and I&#8217;m sure it won&#8217;t be the last. Just to get off on the right foot, let me give the definition of the word from thesite <a href="http://www.innumeracy.com/" class="newpage">innumeracy.com</a>:</p>
<blockquote><p>A term meant to convey a person&#8217;s inability to make sense of the numbers that run their lives. Innumeracy was coined by cognitive scientist Douglas R Hofstadter in one of his Metamagical Thema columns for Scientific American in the early nineteen eighties. Later that decade mathematician John Allen Paulos published the book Innumeracy. In it he includes the notion of chance as well to that of numbers.</p></blockquote>
<p>The example of innumeracy found in this post is somewhat more interesting than most, because it comes from a source that really should know better: <a href="http://discovermagazine.com/" class="newpage">Discover Magazine</a>.<br />
<span id="more-126"></span><br />
In the July 2008 of Discover Magazine, I was reading an article titled <a href="http://discovermagazine.com/2008/jul/16-ocean-acidification-a-global-case-of-osteoporosis" class="newpage">Ocean Acidification: A Global Case of Osteoporosis</a>, and saw this quote:</p>
<blockquote><p>One such event occurred 55 million years ago at the so-called Paleocene-Eocene Thermal Maximum (PETM), when 4.5 million tons of greenhouse gases were released into the atmosphere. </p></blockquote>
<p>Now, we&#8217;re supposedly talking about an event in which so much greenhouse gas was emitted that extraordinary climate change occurred. Is 4.5 million tons really a lot? Checking the Wikipedia <a href="http://en.wikipedia.org/wiki/Greenhouse_gas" class="newpage">article on greenhouse gas emissions</a> gave this interesting quote:</p>
<blockquote><p>According to a preliminary estimate by the Netherlands Environmental Assessment Agency, the largest national producer of CO2 emissions since 2006 has been China with an estimated annual production of about 6200 megatonnes. China is followed by the United States with about 5,800 megatonnes.</p></blockquote>
<p>So the US and China produce 12 <strike>million</strike> billion tons of CO2 in a year, while the PETM produced 4.5 million tons. And the PETM was a major event that we are blowing away every year, year after year? Something is not right here.</p>
<h4>Check the Source</h4>
<p>Fortunately, Discover references the source of their information right on the web page, and quick check of <a href="http://www.geosc.psu.edu/people/faculty/personalpages/tbralower/Bowenetal2006.pdf" class="newpage">the paper</a> shows what the actual number is supposed to be:</p>
<blockquote><p>Atmospheric temperatures inferred from surface ocean (references in Zachos et al. [2005]) and terrestrial (e.g., Wing et al. [2005]) proxies warmed by 5 &#8211; 9° C globally during the PETM. Warming was closely associated with the release of between ~1500 and 4500 Gt of carbon to the ocean and atmosphere, resulting in large but poorly quantified increases in atmospheric CO2 levels [Zachos et al., 2005].
</p></blockquote>
<p>Okay, so in my book, Gt means Gigatonne, and regardless of whether we are using English or Metric units, that&#8217;s going to be measured in billions, not millions of tons.</p>
<p>How did Discover take this number from the paper and mangle it by three orders of magnitude? We&#8217;ll never know. But avoid innumeracy, try to be aware of just how big the earth is, and realize that what seem like big numbers don&#8217;t always do it justice.</p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2008/07/20/innumeracy-part-n/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>A Floating Point Problem</title>
		<link>http://marknelson.us/1996/04/01/a-floating-point-problem/</link>
		<comments>http://marknelson.us/1996/04/01/a-floating-point-problem/#comments</comments>
		<pubDate>Mon, 01 Apr 1996 14:44:33 +0000</pubDate>
		<dc:creator>Mark Nelson</dc:creator>
				<category><![CDATA[Magazine Articles]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://test.kewby.com/?p=10</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/1996/04/01/a-floating-point-problem/' addthis:title='A Floating Point Problem' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>An example of how you can run into trouble when performing floating point comparisons.]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/1996/04/01/a-floating-point-problem/' addthis:title='A Floating Point Problem' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><p>Probably the scariest thing I have to do at work each day is to walk past Marc Leger&#8217;s office. Since Marc&#8217;s office is on the way to the bathroom, I have a tough time avoiding it. So several times a day, I have to face the possibility that Marc will accost me at a time when I am really in a hurry to be elsewhere.</p>
<p>Today was not going to be one of those lucky days when I got off the hook. I slipped down the hallway as quietly as I could, but I wasn&#8217;t quiet enough. Just as I reached Marc&#8217;s office, I heard the familiar demand. &#8220;Mark! Mark! Come here, I need help!&#8221;</p>
<h4>Into the breach</h4>
<p>With a sigh of sympathy for my bladder, I pulled up a chair behind Marc&#8217;s desk. He was running Turbo Debugger, and had a program similar to that shown in <a href="/attachments/1996/fp/fp1.cpp">fp1.cpp</a>.</p>
<p>Marc was working on a customer problem. A Greenleaf Database Library user was attempting to insert floating point data into a database, and our library was returning an error code indicating a loss of precision. Marc was in his usual state of consternation for two reasons. First, he hadn&#8217;t seen this problem occur before. Second, he couldn&#8217;t reproduce the problem when using doubles, just floats.</p>
<h4>The smoking gun</h4>
<p>The offending code is fairly simple. It converts a C++ double to ASCII representation for storage in a database. After converting and storing the result, the code wants to see if any loss of precision was caused during the conversion process. For example, if I&#8217;m using 2 digits after the decimal point, I should get an error if I try to store 3.141. The trailing 1 would be lopped off by the binary to ASCII conversion done by sprintf(). Marc&#8217;s test program from Listing 1 produced the following output:</p>
<pre>
    add_double( 1.12 ) returns success
    add_double( 1.125 ) returns failure
    add_double( d ) returns success
    add_double( f ) returns failure
</pre>
<p>As expected, when using two digits of precision, 1.12 is added to the database without error. 1.125 fails, because it will be stored in ASCII as 1.12. Using a double that has been assigned the value of 1.12 works properly. But using a float with a value of 1.12 fails!</p>
<h4>Seeing double</h4>
<p>The thing that was really bothering Marc was the display on his debugger. He was at the end of the add_double() routine, and had all three local variables in his watch window. They all looked perfect. The two floating point numbers had values of 1.12, and the character buffer contained a &#8220;1.12&#8243;. Even so, the comparison &#8220;test == d&#8221; had just failed, causing the routine to return an error. Was the compiler somehow at fault? Marc was convinced it was a conspiracy on Borland&#8217;s part to make his life hell.</p>
<p>Mark&#8217;s problem was fairly simple, once you looked at it from the right perspective. Numbers such as 1.12 can&#8217;t be represented exactly in a float, or even in a double. Thus, there are rounding and truncation errors when the conversion takes place. The specific problem in <a href="/attachments/1996/fp/fp1.cpp">fp1.cpp</a> is the loss of precision found when placing 1.12 in a float. Assigning that value to a double later on doesn&#8217;t fix the problem, it only perpetuates it.</p>
<p>In the add_double() routine, the actual value passed using a float is just a little bit off from the desired value of 1.12. But printing the value out to a buffer using just two digits of precision manages to throw out the error. Thus, when atof() converts the buffer back to a double, the error is gone. This means that the input value and the test value are going to differ by a small version.</p>
<p><a href="/attachments/1996/fp/fp2.cpp">fp2.cpp</a> is a program that demonstrates how this works. d1 is a double that has been initialized with the value of 1.12. d2 has the same value after being initialized using a float. The output of the program is shown below:</p>
<pre>
f  = 1.12  1.120000005  dump: 29 5c 8f 3f
d1 = 1.12  1.12         dump: ec 51 b8 1e 85 eb f1 3f
d2 = 1.12  1.120000005  dump: 00 00 00 20 85 eb f1 3f
</pre>
<p>As you can see, looking at all three values with just 3 digits of precision makes them look identical. However, when you use a greater precision, the representation error of a float rears its ugly head. The binary dump of the second double shows exactly where the problem lies. The lower half of the double contains all zeros, a result of having the smaller float value copied into it. Clearly, when comparing (test == d ) in fp1.cpp, the compiler will notice the difference.</p>
<h4>A Happy Camper</h4>
<p>Marc wasn&#8217;t particularly happy with my explanation. First, it didn&#8217;t offer an immediate solution to his problem. And second, he resented my glib advice: &#8220;Never use floating point numbers if you expect your program to work.&#8221;</p>
<p>The best answer for our customer would have been to keep all floating point data in doubles at all times. Unfortunately, this solution was impractical. Instead, we created a short routine for her that simply rounded off doubles to 2 significant digits, throwing out anything beyond that. Life would have been much easier if we could have convinced her to simply ignore the error return!</p>
<p>My advice to you is the same: avoid floating point anytime it isn&#8217;t really necessary. If you do find you need to use it, try to avoid mixing doubles and floats. Stick to the preferred C++ floating format of double for all your data and calculations, and maybe you&#8217;ll avoid those moments of hysteria that Marc has to constantly deal with. </p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/1996/04/01/a-floating-point-problem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

