I was browsing the internet for different method to find Pi and I finally found a pretty good one. The only issue is, when you give it a very large number, it slows down tremendously. Would it be possible to make it find 2500 digits a at a time instead of say 1000000? Also, what would be the most efficient way of counting the amount of numbers it has found so far?
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
Thank you very much,
Resentful