|
-
Feb 24th, 2008, 04:56 PM
#1
Thread Starter
Fanatic Member
Working with BIG numbers or LOTS of decimal places
This code contains quite a few mathematical functions and is capable of handling very large numbers or numbers with lots of decimal places. the limit to how big a number they can handle is not 1.79769313486232E+308 which is the normal double limit, but 1.79769313486232E+308 DIGITS LONG!
functions included are: add, subtract, divide, multiply, square root, mod and power.
they work by using long division, long addition etc
they cannot handle negative numbers and the power function ( y^x ) only supports x being a whole number up to the size of double precision, but y can have decimals and be very large like the rest.
it also needs some work as i know they can be alot faster, any suggestions to make them faster will be greatly appreciated.
here they are, this must be put in a module:
UPDATES:
indented
improved code with si's suggestions
attatched a sample project which uses this module to calculate pi (end of second post)
improved again
Code:
'Long math functions by karl baker
'you are free to use these in your own projects as long as credit is given
Public Function divide(tnum1 As String, tnum2 As String, tplaces As String) As String
Dim result As String
Dim times As Long
Dim val3 As String
Dim loopcount As Long
Dim last As Boolean
Dim num1 As String
Dim num2 As String
Dim places As String
places = tplaces
num1 = tnum1
num2 = tnum2
last = False
'start the loop
Do
'loopcount keeps track of how many dp we have calculated
loopcount = loopcount + 1
result = 0
times = 0
'see how many times num1 goes into num2
Do Until morethan(result, num1)
result = add(result, num2)
times = times + 1
Loop
result = subtract(result, num2)
times = times - 1
'if num1 goes into num2 exactly then this is the last calculation we need to do
If result = num1 Then last = True
If loopcount <> places And last = False Then
val3 = subtract(num1, result)
'multiply num1 by 10 to use in the next loop round for calculating the next digit
num1 = multiply(val3, 10)
End If
If loopcount = 1 And last = False Then
divide = times & "."
Else
divide = divide & times
End If
DoEvents
Loop Until loopcount = places Or last = True
If InStr(divide, ".") > 0 Then
Do While Right(divide, 1) = "0"
divide = Left(divide, Len(divide) - 1)
Loop
End If
End Function
Public Function sqrt(tnum1 As String) As String
Dim num1 As String
num1 = tnum1
Dim tempnum1 As String
Dim lastnum As String
Dim multiply1 As String
tempnum1 = 2
lastnum = 1
Do
'square tempnum
multiply1 = multiply(tempnum1, tempnum1)
'if tempnum^2 is bigger than num1 then we know we have found the square root
If morethan(multiply1, num1) Then Exit Do
lastnum = tempnum1
'add the appropriate number to tempnum
If morethan(subtract(num1, multiply1), 1000000000000#) Then
tempnum1 = add(tempnum1, 1000000)
ElseIf morethan(subtract(num1, multiply1), 10000000000#) Then
tempnum1 = add(tempnum1, 100000)
ElseIf morethan(subtract(num1, multiply1), 100000000) Then
tempnum1 = add(tempnum1, 10000)
ElseIf morethan(subtract(num1, multiply1), 1000000) Then
tempnum1 = add(tempnum1, 1000)
ElseIf morethan(subtract(num1, multiply1), 10000) Then
tempnum1 = add(tempnum1, 100)
ElseIf morethan(subtract(num1, multiply1), 100) Then
tempnum1 = add(tempnum1, 10)
ElseIf morethan(subtract(num1, multiply1), 50) Then
tempnum1 = add(tempnum1, 5)
ElseIf morethan(subtract(num1, multiply1), 10) Then
tempnum1 = add(tempnum1, 3)
Else
tempnum1 = add(tempnum1, 1)
End If
DoEvents
Loop
sqrt = lastnum
End Function
Public Function Lmod(tnum1 As String, tnum2 As String) As String
Dim result As String
Dim num1 As String
Dim num2 As String
num1 = tnum1
num2 = tnum2
result = 0
Do Until morethan(result, num1)
result = add(result, num2)
DoEvents
Loop
'subtract to get the remainder we're after
Lmod = subtract(result, num1)
If Lmod = tnum2 Then Lmod = 0
End Function
Public Function add(tnum1 As String, tnum2 As String) As String
Dim num1 As String
Dim num2 As String
num1 = tnum1
num2 = tnum2
Dim i As Long
Dim length As Long
Dim temp As Byte
Dim carry As Byte
checkdec:
'check whether the numbers contain a decimal place
If InStr(num1, ".") > 0 And InStr(num2, ".") > 0 Then
'if they do then format them so that the decimal place is in the same pasition for both of them
If (Len(num1) - InStr(num1, ".")) < (Len(num2) - InStr(num2, ".")) Then
Do
num1 = num1 & "0"
Loop Until (Len(num1) - InStr(num1, ".")) = (Len(num2) - InStr(num2, "."))
ElseIf (Len(num1) - InStr(num1, ".")) > (Len(num2) - InStr(num2, ".")) Then
Do
num2 = num2 & "0"
Loop Until (Len(num1) - InStr(num1, ".")) = (Len(num2) - InStr(num2, "."))
End If
ElseIf InStr(num1, ".") > 0 And InStr(num2, ".") = 0 Then
num2 = num2 & "."
GoTo checkdec
ElseIf InStr(num1, ".") = 0 And InStr(num2, ".") > 0 Then
num1 = num1 & "."
GoTo checkdec
End If
If Len(num1) > Len(num2) Then
length = Len(num1)
num2 = String$(length - Len(num2), "0") & num2
ElseIf Len(num2) > Len(num1) Then
length = Len(num2)
num1 = String$(length - Len(num1), "0") & num1
Else
length = Len(num1)
End If
carry = 0
'start adding the numbers together
For i = 1 To length
If Mid(num1, (length - i + 1), 1) = "." Then
add = "." & add
Else
temp = Val(Mid(num1, (length - i + 1), 1)) + Val(Mid(num2, (length - i + 1), 1)) + carry
If temp < 10 Then
add = temp & add
carry = 0
Else
add = Right(temp, 1) & add
carry = Left(temp, 1)
End If
End If
Next i
If carry > 0 Then add = carry & add
Do While Left(add, 1) = "0"
add = Right(add, Len(add) - 1)
Loop
If Left(add, 1) = "." Then add = "0" & add
End Function
Public Function morethan(tnum1 As String, tnum2 As String) As Boolean
Dim i As Long
Dim length As Long
Dim temp As Byte
Dim carry As Byte
Dim num1 As String
Dim num2 As String
num1 = tnum1
num2 = tnum2
checkdec:
'format just like in add
If InStr(num1, ".") > 0 And InStr(num2, ".") > 0 Then
If (Len(num1) - InStr(num1, ".")) < (Len(num2) - InStr(num2, ".")) Then
Do
num1 = num1 & "0"
Loop Until (Len(num1) - InStr(num1, ".")) = (Len(num2) - InStr(num2, "."))
ElseIf (Len(num1) - InStr(num1, ".")) > (Len(num2) - InStr(num2, ".")) Then
Do
num2 = num2 & "0"
Loop Until (Len(num1) - InStr(num1, ".")) = (Len(num2) - InStr(num2, "."))
End If
ElseIf InStr(num1, ".") > 0 And InStr(num2, ".") = 0 Then
num2 = num2 & "."
GoTo checkdec
ElseIf InStr(num1, ".") = 0 And InStr(num2, ".") > 0 Then
num1 = num1 & "."
GoTo checkdec
End If
If Len(num1) > Len(num2) Then
length = Len(num1)
num2 = String$(length - Len(num2), "0") & num2
ElseIf Len(num2) > Len(num1) Then
length = Len(num2)
num1 = String$(length - Len(num1), "0") & num1
Else
length = Len(num1)
End If
morethan = False
'check if it is more than the other
For i = 1 To length
If Mid(num1, i, 1) <> "." Then
Select Case Val(Mid(num1, i, 1))
Case Is > Val(Mid(num2, i, 1))
morethan = True
Exit Function
Case Is < Val(Mid(num2, i, 1))
morethan = False
Exit Function
End Select
End If
Next i
End Function
continued in next post
Last edited by killo; Feb 27th, 2008 at 11:30 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|