Code Focused
BigInteger for Astronomically Large Numbers
On VB columnist Joe Kunk explores the new BigInteger structure in .NET 4 and how it lets you work with astronomically large numbers.
The BigInteger structure was introduced in the .NET Framework 4, allowing for an arbitrarily large integer number. Prior to this, the largest integer that could be represented was the int64.MaxValue of 9,223,372,036,854,775,807 or approximately 9.2 x 1018. This certainly has been large enough to represent any integer value I have ever needed. Anything larger is truly an astronomical figure. We explore the new BigInteger structure with a sample program that converts distances in light years to inches.
The figures in this article exceed the precision of most handheld calculators. If you want to follow along and have Windows 7, you can perform these calculations with the Windows 7 calculator in scientific mode.
How many inches in a light year? The speed of light is exactly 299,792,458 meters per second. One year is 31,556,926 seconds. Therefore light travels 9,460,528,412,464,108 meters per year. One meter is 39.3700787401575 inches. I calculate the distance traveled by light in a year to be 372,461,748,522,209,163 inches (3.72 x 1017).
Even a light year in inches is not large enough to require the BigInteger structure. A quick calculation shows that the maximum 64-bit integer can represent a little over 24.763 light years in inches. To give you a little perspective on the size of the numbers we are working with, the space probe Voyager 1 was approximately 16 light-hours away from Earth at the time of this writing, after 33 years of travel. To travel enough inches to require our BigInteger structure, it will have to travel at its current rate of speed for almost another 620,000 years.
Our nearest known star, Proxima Centauri, is 4.22 light-years away, too close for our purposes. Researchers announced on September 29, 2010 that an Earth-sized planet named Gliese 581g was found orbiting in the habitable zone of its red dwarf star and would almost certainly contain life. At only 20 light years away, it is still too close in inches for our BigInteger structure. Recently another planet, named GJ1214b, which is six times the size of Earth and comprised mostly of water, was found orbiting a red dwarf star about 40 light years away. Finally we have a planet far enough away in inches to require our BigInteger structure. So approximately how far away is planet GJ1214b in inches?
BigInteger is found in the System.Numerics namespace. I declare the variable OneLightYearInches as a BigInteger to eliminate the need for casting in the calculation. Note that a BigInteger value cannot be a constant because it is a structure and not a value type. The code below shows our BigInteger light year to inches conversion from the sample program.
Dim OneLightYearInches As System.Numerics.BigInteger = 372469703661417000
Dim LightYears As System.Numerics.BigInteger = 0
System.Numerics.BigInteger.TryParse(Me.txtLightYears.Text, LightYears)
Me.txtInches.Text = (LightYears * OneLightYearInches).ToString
Our sample program shows planet GJ1214b to be approximately 14,898,788,146,456,680,000 inches (1.4 x 1019) from the Earth. The center of our galaxy, the Milky Way, is about 26,000 light years away, or 9,684,212,295,196,842,000,000 inches (9.6 x 1021). Be careful to count them carefully on your way there!
Now that we can easily compute values in BigInteger, the next question is performance. What is the performance of BigInteger compared to Int64? To determine this, an integer random value is obtained, then added to itself 500 million times, first as an int64 value and then as a BigInteger value, with the calculation times compared. See Figure 1.
[Click on image for larger view.] |
Figure 1. Comparing Int64 and BigInteger performance. |
The BigInteger calculation loop is over 52 times slower. Both the Int64 and BigInteger values are immutable; a new copy of the value is created in memory each time it is modified. In fact all integral types, including the venerable Integer data type, are immutable. The extra complexity of creating an arbitrarily large number, even when the number is no larger than a standard numeric type, causes the difference in performance. To minimize this performance penalty, especially when modifying BigInteger values in loops, perform as many calculations in standard integral types as possible and assign to the BigInteger structure only when necessary.
Constructing a BigInteger is easy if the initial value is integral within the range of an Int64 value. Both of the following statements are valid:
Dim Init1 As System.Numerics.BigInteger = 123456789
Dim Init2 As New System.Numerics.BigInteger(123456789)
If the initial value is larger than Int64.MaxValue, the BigInteger can be initialized with the TryParse method, or initialized with a byte array such as:
Dim byteArray() As Byte = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12}
Dim LargeBigInteger As New System.Numerics.BigInteger(byteArray)
The BigInteger constructor expects the low-order bytes to precede the higher-order bytes in the array.
The ToString() method supports a maximum of 50 significant digits in most cases; any digits beyond that become zero. If your BigInteger value may exceed 50 significant digits, use the ToString("R0") format rather than ToString("N0").
Conclusion
The BigInteger structure, introduced in the .NET Framework 4, represents integers of arbitrary size but should be used only when the Long type is not sufficient, due to the inherent overhead of constructing a variable-sized value. For applications where truly astronomical sized integrals are required, they are now available in managed code with nearly the same ease of use as standard integrals.
About the Author
Joe Kunk is a Microsoft MVP in Visual Basic, three-time president of the Greater Lansing User Group for .NET, and developer for Dart Container Corporation of Mason, Michigan. He's been developing software for over 30 years and has worked in the education, government, financial and manufacturing industries. Kunk's co-authored the book "Professional DevExpress ASP.NET Controls" (Wrox Programmer to Programmer, 2009). He can be reached via email at [email protected].