DCSIMG
December 2011 - Posts - Pavel's Blog
Sign in | Join | Help

Pavel's Blog

Pavel is a software guy that is interested in almost everything
software related... way too much for too little time

December 2011 - Posts

Calculating PI in .NET

Published at Dec 30 2011, 10:31 PM by pavely

I always loved mathematics. Although I’m certainly not a mathematician by profession, I’m always intrigued and inspired by math’s pureness and cleverness. One of the simplest and fascinating aspects of math is the number PI. Described simply as the ratio of a circle’s circumference to its diameter, it’s a constant with infinite digits after the decimal point and most importantly, non repeating (at least as far as I know).

There are many ways to calculate PI, as evident within the PI Wikipedia link. I wanted to see how I can get a large number of digits of PI with a C# program.

As every high school kid knows, PI in radians is equal to 180 degrees, or half a circle. And since the tangent of 45 (PI/4) degrees is 1, PI can be calculated like so:

PI/4 = arctan(1) or PI = 4 * arctan(1)

This looks simple enough. Just need to calculate the arc (inverse) tangent of 1. Of course, a method like Math.ATan is out of the question. It (and its kind) work with doubles, which gives a fixed 15 digit precision, while we want arbitrary precision.

How should we calculate the arc tangent of 1? One option is to use the Taylor series expansion (valid for |x|<= 1):

arctan(x) = x - x^3/3 + x^5/5 - x^7/7 + x^9/9 –…

The ^ sign indicates “to the power of”. If x is 1 (as is in our case), the series is simplified:

arctan(1) = 1 – 1/3 + 1/5 – 1/7 + 1/9 –…

Nothing to it, right?

But how do we calculate that? Again, using just doubles will get us nowhere better than Math.PI. We need an arbitrary sized floating point number. This does not exist in .NET (at least not yet). So, we’ll take the next best thing: the BigInteger type introduced in .NET 4. This is an arbitrarily large integer; all we have to do is use the above formula, but multiply everything by some large BigInteger, such as 10 to the 100th power, and interpret the final result as being larger by that factor. Let’s write a PI calculating method based on this series:

arctan(1)*4 as PI
  1. private static BigInteger CalculatePiSlow(int iterations, int digits) {
  2.     var mag = BigInteger.Pow(10, digits);
  3.     var sum1 = Enumerable.Range(0, iterations / 2).Select(i => i * 4 + 1).Aggregate(BigInteger.Zero, (sum, i) => sum += mag / i);
  4.     var sum2 = Enumerable.Range(0, iterations / 2).Select(i => i * 4 + 3).Aggregate(BigInteger.Zero, (sum, i) => sum += mag / i);
  5.     return 4 * (sum1 - sum2);
  6. }

If you’re not familiar with the LINQ Aggregate operator, here’s a brief explanation: it’s the generic way operators like Sum and Average work: we use an “accumulator”, starting at BigInteger.Zero, and decide with the second argument (a delegate) what to do with the incoming number. The Sum operator does not work here because there is no overload that takes a BigInteger (although it would be simple enough to add such an extension method. I’ll leave it as an exercise for the interested reader).

iterations indicates the number of terms we wish to take into account and digits indicates the maximum digits we wish to calculate. Calling this method with 1000 iterations and just 20 digits yields the following:

image

I’ve printed Math.PI as a basic comparison. The result is disappointing – the fourth digit is wrong (“0” instead of “1”). Let’s bump up the iterations to 2000:

image

No significant change. That same digit is still wrong. How about 10000 iterations?

image

This is better. The fourth digit is correct, but the fifth is not. Let’s get crazy and go for a million iterations:

image

Better still, but we’re not even at Math.PI. Ok, let’s go super-crazy and try 100 million iterations:

image

This actually took a fair amount of time, but the result is still disappointing. Clearly, something must change.

The problem with this series is that it converges slowly for large x (close to 1). In fact, for very small x values, it converges pretty fast. We need a new formula.

In 1706, John Machin found this formula to calculate PI:

image

At first, this may seem worse: now we have to calculate two arctangents! But, as the numbers are much smaller than one, we should get a better rate of convergence.

First, we’ll have to write a general arc tangent function, as none exists in BigInteger. This is a simple variant of the above calculation that needs to raise to the appropriate power – a simple enough job as BigInteger natively supports it:

Arc Tangent for BigInteger
  1. static BigInteger ArcTan(int oneOverX, int iterations, int digits) {
  2.     var mag = BigInteger.Pow(10, digits);
  3.     var sum1 = Enumerable.Range(0, iterations / 2).Select(i => i * 4 + 1).Aggregate(BigInteger.Zero, (sum, i) => sum += mag / (i * BigInteger.Pow(oneOverX, i)));
  4.     var sum2 = Enumerable.Range(0, iterations / 2).Select(i => i * 4 + 3).Aggregate(BigInteger.Zero, (sum, i) => sum += mag / (i * BigInteger.Pow(oneOverX, i)));
  5.     return sum1 - sum2;
  6. }

The last part uses the BigInteger.Pow method to raise to the appropriate power. Now we can write the new PI calculation method like so:

Faster PI calculation
  1. private static BigInteger CalculatePiQuick(int n, int digits) {
  2.     return 4 * (4 * ArcTan(5, n, digits) - ArcTan(239, n, digits));
  3. }

Running this with 20 iterations and 20 digits yields:

image

The result already surpasses Math.PI, and is calculated in a fraction of a second. We can try 1000 for the iterations and digits and get the first 1000 digits (or so) of PI pretty quickly (less than half a second without any optimizations):

image

The last 6 digits are in fact wrong (we need a few more iterations to get them right).

Now here’s a challenge for you: memorize as many digits as you can…

Getting Device Information in Windows Phone 7

Published at Dec 19 2011, 06:30 PM by pavely

Windows Phone 7 mandates a set of minimum requirements from devices it runs on, such as camera resolution, hardware graphics support, the existence of sensors such as microphone, GPS, touch, etc. However, sometimes it’s useful to know the exact specifications of a particular device the application is running on, so the application can optimize. As a simple example, running on the emulator or a real device can make a huge difference – maybe the application has a way of doing things differently when running on the emulator for testing purposes.

The device information is exposed primarily through the Microsoft.Phone.Info.DeviceStatus static class, where various properties provide some useful (and some not so useful) information. One oddity is that the device type (emulator or real device) is exposed through a different static property, Microsoft.Devices.Environment.DeviceType.

For demo purposes, I’ve created a simple class that wraps some of these properties in a type suitable for data binding (no {x:Static} on WP7 yet Sad smile):

  1. public class AppDeviceState {
  2.     public DeviceType DeviceType {
  3.         get {
  4.             return Microsoft.Devices.Environment.DeviceType;
  5.         }
  6.     }
  7.  
  8.     public string DeviceName {
  9.         get { return DeviceStatus.DeviceName; }
  10.     }
  11.  
  12.     public long TotalMemory {
  13.         get { return DeviceStatus.DeviceTotalMemory >> 20; }
  14.     }
  15.  
  16.     public PowerSource PowerSource {
  17.         get { return DeviceStatus.PowerSource; }
  18.     }
  19.  
  20.     public string DeviceManufacturer {
  21.         get { return DeviceStatus.DeviceManufacturer; }
  22.     }
  23. }

TotalMemory returns the result in megabytes, which is easier to use than the size in bytes.

Here’s a simple Grid that hosts some TextBlocks that bind to these properties:

  1. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  2.     <Grid.Resources>
  3.         <Style TargetType="TextBlock">
  4.             <Setter Property="FontSize" Value="24" />
  5.         </Style>
  6.     </Grid.Resources>
  7.     <Grid.RowDefinitions>
  8.         <RowDefinition Height="Auto" />
  9.         <RowDefinition Height="Auto" />
  10.         <RowDefinition Height="Auto" />
  11.         <RowDefinition Height="Auto" />
  12.         <RowDefinition Height="Auto" />
  13.     </Grid.RowDefinitions>
  14.     <Grid.ColumnDefinitions>
  15.         <ColumnDefinition Width="Auto" />
  16.         <ColumnDefinition Width="20" />
  17.         <ColumnDefinition />
  18.     </Grid.ColumnDefinitions>
  19.     <TextBlock Text="Device Name:" />
  20.     <TextBlock Grid.Column="2" Text="{Binding DeviceName}"/>
  21.     <TextBlock Grid.Row="1" Text="Device Type:" />
  22.     <TextBlock Grid.Row="1" Grid.Column="2" Text="{Binding DeviceType}"/>
  23.     <TextBlock Grid.Row="2" Text="Total Memory (MB):" />
  24.     <TextBlock Grid.Row="2" Grid.Column="2" Text="{Binding TotalMemory}"/>
  25.     <TextBlock Grid.Row="3" Text="Power Source:" />
  26.     <TextBlock Grid.Row="3" Grid.Column="2" Text="{Binding PowerSource}" />
  27.     <TextBlock Grid.Row="4" Text="Manufacturer:" />
  28.     <TextBlock Grid.Row="4" Grid.Column="2" Text="{Binding DeviceManufacturer}" />
  29. </Grid>

In the page constructor, the binding source is set through a DataContext:

  1. public MainPage() {
  2.     InitializeComponent();
  3.  
  4.     DataContext = new AppDeviceState();
  5. }

This is the result on the emulator:

image

And this is the result on my actual device:

image

The demo project is attached.

My Sessions at the MobiWeb Conference

Published at Dec 16 2011, 12:21 PM by pavely

The MobiWeb Conference is scheduled for the 15-17 of January in the Daniel Hotel in Hertzliya (Israel). The sessions in the conference are “one day seminars”, each seminar covering some topic related to web development, mobile development, or both.

I’ll be presenting two seminars at the conference. The fist, “Building Windows Phone 7 Apps with Silverlight” (on the 16th) will cover the development for the (relatively new) Windows Phone platform using Silverlight (and maybe some XNA if we have time). Anyone looking into developing applications for this exciting and capable platform should get a good head start by attending this seminar. Basic familiarity with Silverlight will be beneficial, although I’ll go over the basics fairly quickly.

The second seminar I’ll be presenting is “Silverlight 5.0 Workshop” (on the 17th). This seminar will cover Silverlight development, from the basics, quickly moving to more advanced topics. It is intended for those who don’t know Silverlight, or have some basic familiarity with it. This can serve as a basis for general Silverlight development, or more specifically, for Windows Phone (it might make more sense to switch the seminar dates, so someone without any background in Silverlight or Windows Phone could follow up from Silverlight to Windows Phone sequentially; I’m looking into it). The seminar will also discuss some of the new features introduced in Silverlight 5.

Register here by leaving your details.

Maybe I’ll see you there!

Announcing the Israeli Windows Phone User Group

Published at Dec 08 2011, 07:44 PM by pavely

Although Windows Phone is not yet officially launched in Israel, it’s time for Israeli developers to start developing for the Windows Phone platform, even if most don’t have an actual device at hand.

A new user group dedicated to development for Windows Phone has been created, managed by Tomer Shamam and yours truly. The first meeting will be held on December 27th at the Microsoft Offices in Ra’anana. Please use this link to register and view the agenda: http://introwindowsphone.eventbrite.com

In this first meeting, Tomer and I will talk about the Windows Phone ecosystem, where to get tools and other resources, and then dive in to discuss application development using Silverlight.

Note that we plan to distribute 2 actual Windows Phone devices to participants in the meeting, so that at least some of you can test applications on an actual device!

We hope to see you there!

WPF Tip: Binding to the Selected Item in a Master-Details View

Published at Dec 06 2011, 04:00 PM by pavely

Master-details is a common way to display data. A master view provides minimal data for a collection of objects (e.g. book names), and when selecting one such item, a details view provides more information for the selected item (e.g. a book’s name, author, publication date, etc.).

In WPF, data binding (in XAML) is typically used to achieve the connection between an object and its details without using any code. Let’s see how we can achieve this.

Let’s say we want to show a list of book names, and when a book is selected, we want to show its details. The complete application might look like so:

image

The windows contains a Grid with two rows. The top row hosts a ListBox, while the bottom row hosts a StackPanel with a bunch of simple TextBlocks inside. Here’s the basic ListBox markup:

  1. <ListBox ItemsSource="{Binding}" HorizontalContentAlignment="Stretch">
  2.     <ListBox.ItemTemplate>
  3.         <DataTemplate>
  4.             <Border BorderBrush="Blue" BorderThickness="2" Margin="0" Padding="4" CornerRadius="4" x:Name="border">
  5.                 <TextBlock TextAlignment="Center" Text="{Binding Name}" Foreground="Black" FontWeight="Bold" FontSize="16" x:Name="text"/>
  6.             </Border>
  7.             <DataTemplate.Triggers>
  8.                 <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBoxItem}}" Value="True">
  9.                     <Setter Property="Background" Value="Yellow" TargetName="border" />
  10.                 </DataTrigger>
  11.             </DataTemplate.Triggers>
  12.         </DataTemplate>
  13.     </ListBox.ItemTemplate>
  14. </ListBox>

The data trigger is of no significance as it just sets the selected item’s background as yellow.

The ItemsSource property is bound to the nearest DataContext up the visual tree. We’ll set that context in code (for simplicity) in the Window’s constructor:

  1. var books = new ObservableCollection<Book> {
  2.     new Book { Name = "Windows Internals", Author = "Mark Russinovich", Published = new DateTime(2009, 6, 17) },
  3.     new Book { Name = "Essential COM", Author = "Don Box", Published = new DateTime(1998, 1, 1) },
  4.     new Book { Name = "Programming Windows with MFC", Author = "Jeff Prosise", Published = new DateTime(1999, 5, 13) },
  5.     new Book { Name = "Astrology of Fate", Author = "Liz Greene", Published = new DateTime(1984, 11, 1) },
  6.     new Book { Name = "Windows via C/C++", Author = "Jeffrey Richter", Published = new DateTime(2007, 12, 12) },
  7.     new Book { Name = "CLR Via C#", Author = "Jeffrey Richter", Published = new DateTime(2010, 2, 11) },
  8.     new Book { Name = "Pro WPF in C# 2010", Author = "Matthew Macdonald", Published = new DateTime(2009, 12, 23) },
  9. };
  10.  
  11. DataContext = books;

Now for the details part. How can we bind the TextBlocks Text property to the currently selected item in the ListBox? Here’s one way to do it:

  1. <StackPanel Grid.Row="1" TextBlock.FontSize="16" DataContext="{Binding SelectedItem, ElementName=_list}">
  2.     <TextBlock Margin="4" Text="{Binding Name, StringFormat=Name: {0}}" />
  3.     <TextBlock Margin="4" Text="{Binding Author, StringFormat=Author: {0}}" />
  4.     <TextBlock Margin="4" Text="{Binding Published, StringFormat=Published: {0:d}}" />
  5. </StackPanel>

This assumes the ListBox is named _list. Although this works, it’s a bit too specific: we’re looking up the SelectedItem of a specific control. What happens if that control is later replaced with something else (like a ComboBox) and is named differently? What is the ListBox is removed altogether and selection is controlled programmatically via some other UI elements?

It turns out, we can do better. We need to add the IsSynchronizedWithCurrentItem=”true” to the ListBox. This will use the default view, that sits between the ListBox and the actual data collection (the books). Now we can bind to the view, by hooking up to the CurrentItem property (from the ICollectionView interface implemented by the view):

  1. <StackPanel Grid.Row="1" TextBlock.FontSize="16" DataContext="{Binding CurrentItem}">

That’s better. No dependency on any specific ListBox. Can we make it even better? We can. We’ll remove the local DataContext on the StackPanel and prepend a forward slash (/) to the property names within the TextBlocks Text property, like so:

  1. <StackPanel Grid.Row="1" TextBlock.FontSize="16" >
  2.     <TextBlock Margin="4" Text="{Binding /Name, StringFormat=Name: {0}}" />
  3.     <TextBlock Margin="4" Text="{Binding /Author, StringFormat=Author: {0}}" />
  4.     <TextBlock Margin="4" Text="{Binding /Published, StringFormat=Published: {0:d}}" />
  5. </StackPanel>

Note the slash in the bound properties (/Name, /Author, /Published). We simply pick the relevant properties on a single item (book in our example). Note that the IsSynchronizedWithCurrentItem must be set to true, as before.

Parallel Programming Open House Session

Published at Dec 01 2011, 05:34 PM by pavely

Today I presented a half-day session on Multithreading & Parallel Programming at John Bryce center in Tel Aviv. Thank you all for attending! I certainly enjoyed presenting these fascinating topics.

I’ve attached the demos I showed. The presentation will be sent to those who attended by email.

Thank you!