Mega Code Archive

 
Categories / VB.Net Tutorial / Operator
 

Calculate PI

' Quote  from 'Visual Basic 2005 Cookbook Solutions for VB 2005 Programmers 'by Tim Patrick (Author), John Craig (Author) '# Publisher: O'Reilly Media, Inc. (September 21, 2006) '# Language: English '# ISBN-10: 0596101775 '# ISBN-13: 978-0596101770 Public Class Tester     Public Shared Sub Main       Console.WriteLine(FindPi(500))     End Sub     Private Shared NumberDigits As Integer     Public Shared Function FindPi(ByVal digits As Integer) As String         ' ----- Calculate Pi to the specified number of digits,         '       based on the formula:         '          Pi/4 = arctan(1/2) + arctan(1/3)         Dim result As New System.Text.StringBuilder("PI=3.")         Dim digitIndex As Integer         Dim divFactor As Integer         ' ----- Build an array that will hold manual calculations.         NumberDigits = digits + 2         Dim targetValue(NumberDigits) As Integer         Dim sourceValue(NumberDigits) As Integer         ' ---- Perform the calculation.         divFactor = 2         ArcTangent(targetValue, sourceValue, divFactor)         divFactor = 3         ArcTangent(targetValue, sourceValue, divFactor)         ArrayMult(targetValue, 4)         ' ----- Return a string version of the calculation.         For digitIndex = 1 To NumberDigits - 3             result.Append(Chr(targetValue(digitIndex) + Asc("0"c)))         Next digitIndex         Return result.ToString     End Function     Private Shared Sub ArrayMult(ByRef baseNumber() As Integer, _             ByRef multiplier As Integer)         ' ----- Multiply an array number by another number by hand.         '       The product remains in the array number.         Dim carry As Integer         Dim position As Integer         Dim holdDigit As Integer         ' ----- Multiple each base digit, from right to left.         For position = NumberDigits To 0 Step -1             ' ----- If the multiplication went past 9, carry the             '       tens value to the next column.             holdDigit = (baseNumber(position) * multiplier) + carry             carry = holdDigit \ 10             baseNumber(position) = holdDigit Mod 10         Next position     End Sub     Private Shared Sub ArrayDivide(ByRef dividend() As Integer, ByRef divisor As Integer)         ' ----- Divide an array number by another number by hand.         '       The quotient remains in the array number.         Dim borrow As Integer         Dim position As Integer         Dim holdDigit As Integer         ' ----- Process division for each digit.         For position = 0 To NumberDigits             ' ----- If the division can't happen directly, borrow from             '       the previous position.             holdDigit = dividend(position) + borrow * 10             dividend(position) = holdDigit \ divisor             borrow = holdDigit Mod divisor         Next position     End Sub     Private Shared Sub ArrayAdd(ByRef baseNumber() As Integer, ByRef addend() As Integer)         ' ----- Add two array numbers together.         '       The sum remains in the first array number.         Dim carry As Integer         Dim position As Integer         Dim holdDigit As Integer         ' ----- Add each digit from right to left.         For position = NumberDigits To 0 Step -1             ' ----- If the sum goes beyond 9, carry the tens             '       value to the next column.             holdDigit = baseNumber(position) + addend(position) + carry             carry = holdDigit \ 10             baseNumber(position) = holdDigit Mod 10         Next position     End Sub     Private Shared Sub ArraySub(ByRef minuend() As Integer, ByRef subtrahend() As Integer)         ' ----- Subtract one array number from another.         '       The difference remains in the first array number.         Dim borrow As Integer         Dim position As Integer         Dim holdDigit As Integer         ' ---- Subtract the digits from right to left.         For position = NumberDigits To 0 Step -1             ' ----- If the subtraction would give a negative value             '       for a column, we will have to borrow.             holdDigit = minuend(position) - subtrahend(position) + 10             borrow = holdDigit \ 10             minuend(position) = holdDigit Mod 10             If (borrow = 0) Then minuend(position - 1) -= 1         Next position     End Sub     Private Shared Function ArrayZero(ByRef baseNumber() As Integer) As Boolean         ' ----- Report whether an array number is all zero.         Dim position As Integer         ' ----- Examine each digit.         For position = 0 To NumberDigits             If (baseNumber(position) <> 0) Then                 ' ----- The number is nonzero.                 Return False             End If         Next position         ' ----- The number is zero.         Return True     End Function     Private Shared Sub ArcTangent(ByRef targetValue() As Integer, _             ByRef sourceValue() As Integer, _             ByVal divFactor As Integer)         ' ----- Calculate an arctangent of a fraction, 1/divFactor.         '       This routine performs a modified Maclaurin series to          '       calculate the arctangent. The base formula is:         '          arctan(x) = x - x^3/3 + x^5/5 - x^7/7 + x^9/9 - ...         '       where -1 < x < 1 (it's 1/divFactor in this case).         Dim workingFactor As Integer         Dim incremental As Integer         ' ----- Figure out the "x" part, 1/divFactor.         sourceValue(0) = 1         incremental = 1         workingFactor = divFactor         ArrayDivide(sourceValue, workingFactor)         ' ----- Add "x" to the total.         ArrayAdd(targetValue, sourceValue)         Do             ' ----- Perform the "- (xy)/y" part.             ArrayMult(sourceValue, incremental)             workingFactor = divFactor * divFactor             ArrayDivide(sourceValue, workingFactor)             incremental += 2             workingFactor = incremental             ArrayDivide(sourceValue, workingFactor)             ArraySub(targetValue, sourceValue)             ' ----- Perform the "+ (xy)/y" part.             ArrayMult(sourceValue, incremental)             workingFactor = divFactor * divFactor             ArrayDivide(sourceValue, workingFactor)             incremental += 2             workingFactor = incremental             ArrayDivide(sourceValue, workingFactor)             ArrayAdd(targetValue, sourceValue)         Loop Until ArrayZero(sourceValue)     End Sub      End Class PI=3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211 7067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930 3819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491 4127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151 1609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011 9491