It's not as easy as you might think!
The Visual Basic 2005 Cookbook ... which is a consistent source of interesting stuff ... has a program that will calculate Pi to an arbitrary precision. The downloadable source calculates it to 500 digits. I verified the answer on the web. In checking out the code, I discovered that the multiplication subroutine, at least, fell quite a bit short of the task of multiplying two arbitrarily large numbers.
The problem is that no datatype in VB can contain an arbitrarily large number. The reigning champion is the new .NET Decimal data type that can hold an integer as large as 79,228,162,514,264,337,593,543,950,335. The Cookbook uses an approach that places one number to be multiplied in an array of integers and the other in an integer variable. The array can be (almost) arbitrarily large, but the other is still limited by Visual Basic datatypes. (In the Cookbook program, the calculation of Pi never requires the second number to get bigger than four digits.)
Not that this is a very frequent problem. Wikipedia points out that calculating Pi to extreme precision only has value as an abstract mathematical problem. "A value (of Pi) truncated to 39 decimal places is sufficient to compute the circumference of any circle that fits in the visible universe to a precision comparable to the size of a hydrogen atom."
I'd say that's good enough for government work.
I set out to write a subroutine that would ... and fell a bit short of the task myself. I shouldn't feel so bad. Even the Greek mathematician Archimedes worked on multiplying large numbers and didn't solve the problem completely.
By reversing the array (counting up instead of counting down) and calculating the maximum number of digits to use as the loop limits, I was able to calculate a number about five digits larger than the maximum that Decimal would allow. Here's the code based on the method of the Cookbook:
Dim NumberDigits As Short Dim Multiplier As Decimal Dim Multiplicand(500) As Short Dim Carry As Decimal Dim Position As Short Dim HoldDigit As Decimal Dim I As Short = 0 Multiplier = CDec(TextMultiplier.Text) NumberDigits = TextMultiplicand.Text.Length - 1 For I = NumberDigits To 0 Step -1 Multiplicand(I) = _ CInt(TextMultiplicand.Text.Substring(NumberDigits - I, 1)) Next Carry = 0 For Position = 0 To (2 * NumberDigits - 1) HoldDigit = (Multiplicand(Position) * Multiplier) + Carry Carry = HoldDigit \ 10 Multiplicand(Position) = HoldDigit Mod 10 Next Dim TextProductString As New System.Text.StringBuilder I = 0 For I = (2 * NumberDigits - 1) To 0 Step -1 TextProductString.Append(Multiplicand(I).ToString) Next TextProduct.Text = TextProductString.ToString.TrimStart("0"c)
Pseudocode for a general method can be found at Wikipedia as well. (Converting this into a general program will be left as an exercise for the student.)
'Arrays representing the binary representations 'multiply(a[0..n-1], b[0..n-1]) 'x ? 0 'for i from 0 to 2n-1 'for j from 0 to i 'k ? i - j 'x ? x + (a[j] × b[k]) 'result[i] ? x mod 2 'x ? floor(x/2)
If you run into a requirement like this in real life, one solution is to use the BigInteger function from the Microsoft Visual J# library. Just add a reference to vjslib in your project. The ability of any .NET language to use compiled DLL's from any other comes to the rescue!