danbaron
28-08-2011, 11:47
I had an old script to multiply big integers.
It uses the simplest and slowest method of multiplication, like you would do with a pencil and paper.
I decided to try to add a factorial function.
It works correctly, but, it is really slow.
On my computer it took 448 seconds to find 200!.
In function TBMain(), you specify the value, "n", which you want the factorial of.
Then, you run it.
If, for instance, you set, n=200, then, as the program runs, you will see in the console window, it count down from 200 as it calculates, i.e.,
200
199
198
197
.
.
After it reaches 2, it will display the value of n!.
I checked using Racket, and 200! has 375 digits.
The elapsed time to find 200! in DrRacket was, 0 milliseconds.
At least our answers were the same.
' code ----------------------------------------------------------------------------------------------
Uses "console"
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%neg = -1
%pos = +1
%intsize = 500
Type genint
digit(%intsize) As Byte
sign As Integer
error As Byte
End Type
'--------------------------------------------------------------
Function TBMain()
Local s As String
Local t1, t2, tt As Integer
Local n As Integer
' Set "n", for n!.
n = 200
t1 = Timer
s = genintfactorial(n)
t2 = Timer
tt = t2 - t1
PrintL
PrintL "elapsed time = ", tt, " seconds"
PrintL
PrintL n, " factorial:"
Console_WriteLine(s)
End Function
'--------------------------------------------------------------
Function genintfactorial(n As Integer) As String
Local num1, num2, num3 As genint
Local s As String
Local i As Integer
s = "1"
genintsetvalue(num1,s)
For i = n To 2 Step -1
PrintL i
s = Format$(i)
genintsetvalue(num2,s)
genintmult(num1,num2,num3)
genintsetequal(num1,num3)
Next
Return genintgetstringrep(num3)
End Function
'--------------------------------------------------------------
Function genintsetequal(gn2 As genint, gn1 As genint)
'Set gn2 = gn1.
Local i As DWord
For i = 1 To %intsize
gn2.digit(i) = gn1.digit(i)
Next
End Function
'--------------------------------------------------------------
Function genintsetvalue(gn As genint, vs As String)
Local i, l As DWord
genintzero(gn)
l = Len(vs)
For i = 1 To l
gn.digit(l - i + 1) = Val(Mid$(vs, i, 1))
Next
End Function
'--------------------------------------------------------------
Function genintzero(gn As genint)
Local i As DWord
For i = 1 To %intsize
gn.digit(i) = 0
Next
End Function
'--------------------------------------------------------------
Function genintsetsign(gn As genint, s As Integer)
gn.sign = s
End Function
'--------------------------------------------------------------
Function genintgetstringrep(gn As genint) As String
Local i, j As DWord
Local vs As String
vs = ""
If gn.sign > -1 Then
vs = vs & "+"
Else
vs = vs & "-"
EndIf
i = 0
Do
If %intsize - i = 0 Then Return "0"
If gn.digit(%intsize - i) > 0 Then Exit Do
i += 1
Loop
For j = i + 1 To %intsize
vs = vs & Chr$(48 + gn.digit(%intsize - j + 1))
Next
Return vs
End Function
'--------------------------------------------------------------
Function genintgetsize(gn As genint) As DWord
Local i As DWord
i = 0
Do
If %intsize - i = 0 Then Return 0
If gn.digit(%intsize - i) > 0 Then Exit Do
i += 1
Loop
Return %intsize - i
End Function
'--------------------------------------------------------------
Function genintseterror(gn As genint)
gn.error = TRUE
End Function
'--------------------------------------------------------------
Function genintshiftleft(gn As genint, nplaces As DWord)
Local sz, i, j As DWord
sz = genintgetsize(gn)
For i = 1 To sz
j = sz - i + 1
gn.digit(j + nplaces) = gn.digit(j)
Next
For i = 1 To nplaces
gn.digit(i) = 0
Next
End Function
'--------------------------------------------------------------
Function genintadd(a As genint, b As genint, c As genint)
Local i As DWord
Local s, v, k As Byte
Local asize, bsize, maxsize
Local temp As genint
asize = genintgetsize(a)
bsize = genintgetsize(b)
maxsize = asize
If bsize > maxsize Then maxsize = bsize
genintzero(temp)
k = 0
For i = 1 To maxsize + 1
s = a.digit(i) + b.digit(i) + k
v = Mod(s, 10)
k = s \ 10
temp.digit(i) = v
Next
For i = 1 To %intsize
c.digit(i) = temp.digit(i)
Next
End Function
'--------------------------------------------------------------
Function genintmult(a As genint, b As genint, c As genint)
Local i, j As DWord
Local p, v, k As Byte
Local asize, bsize, tsize As DWord
Local temp As genint
genintzero(c)
genintzero(temp)
asize = genintgetsize(a)
bsize = genintgetsize(b)
tsize = asize + bsize
If tsize > %intsize Then
genintseterror(c)
Return
EndIf
For i = 1 To asize
k = 0
For j = 1 To bsize + 1
p = a.digit(i) * b.digit(j) + k
v = Mod(p, 10)
k = p \ 10
temp.digit(j) = v
Next
genintshiftleft(temp, i - 1)
genintadd(c, temp, c)
genintzero(temp)
Next
End Function
' output --------------------------------------------------------------------------------------------
.
.
5
4
3
2
elapsed time = 448 seconds
200 factorial:
+7886578673647905035523632139321850622951359776871732632947425332443594499634033
42920304284011984623904177212138919638830257642790242637105061926624952829931113
46285727076331723739698894392244562145166424025403329186413122742829485327752424
24075739032403212574055795686602260319041703240623517008587961789222227896237038
97374720000000000000000000000000000000000000000000000000
C:\Users\root\Desktop\NEW THIN>
It uses the simplest and slowest method of multiplication, like you would do with a pencil and paper.
I decided to try to add a factorial function.
It works correctly, but, it is really slow.
On my computer it took 448 seconds to find 200!.
In function TBMain(), you specify the value, "n", which you want the factorial of.
Then, you run it.
If, for instance, you set, n=200, then, as the program runs, you will see in the console window, it count down from 200 as it calculates, i.e.,
200
199
198
197
.
.
After it reaches 2, it will display the value of n!.
I checked using Racket, and 200! has 375 digits.
The elapsed time to find 200! in DrRacket was, 0 milliseconds.
At least our answers were the same.
' code ----------------------------------------------------------------------------------------------
Uses "console"
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%neg = -1
%pos = +1
%intsize = 500
Type genint
digit(%intsize) As Byte
sign As Integer
error As Byte
End Type
'--------------------------------------------------------------
Function TBMain()
Local s As String
Local t1, t2, tt As Integer
Local n As Integer
' Set "n", for n!.
n = 200
t1 = Timer
s = genintfactorial(n)
t2 = Timer
tt = t2 - t1
PrintL
PrintL "elapsed time = ", tt, " seconds"
PrintL
PrintL n, " factorial:"
Console_WriteLine(s)
End Function
'--------------------------------------------------------------
Function genintfactorial(n As Integer) As String
Local num1, num2, num3 As genint
Local s As String
Local i As Integer
s = "1"
genintsetvalue(num1,s)
For i = n To 2 Step -1
PrintL i
s = Format$(i)
genintsetvalue(num2,s)
genintmult(num1,num2,num3)
genintsetequal(num1,num3)
Next
Return genintgetstringrep(num3)
End Function
'--------------------------------------------------------------
Function genintsetequal(gn2 As genint, gn1 As genint)
'Set gn2 = gn1.
Local i As DWord
For i = 1 To %intsize
gn2.digit(i) = gn1.digit(i)
Next
End Function
'--------------------------------------------------------------
Function genintsetvalue(gn As genint, vs As String)
Local i, l As DWord
genintzero(gn)
l = Len(vs)
For i = 1 To l
gn.digit(l - i + 1) = Val(Mid$(vs, i, 1))
Next
End Function
'--------------------------------------------------------------
Function genintzero(gn As genint)
Local i As DWord
For i = 1 To %intsize
gn.digit(i) = 0
Next
End Function
'--------------------------------------------------------------
Function genintsetsign(gn As genint, s As Integer)
gn.sign = s
End Function
'--------------------------------------------------------------
Function genintgetstringrep(gn As genint) As String
Local i, j As DWord
Local vs As String
vs = ""
If gn.sign > -1 Then
vs = vs & "+"
Else
vs = vs & "-"
EndIf
i = 0
Do
If %intsize - i = 0 Then Return "0"
If gn.digit(%intsize - i) > 0 Then Exit Do
i += 1
Loop
For j = i + 1 To %intsize
vs = vs & Chr$(48 + gn.digit(%intsize - j + 1))
Next
Return vs
End Function
'--------------------------------------------------------------
Function genintgetsize(gn As genint) As DWord
Local i As DWord
i = 0
Do
If %intsize - i = 0 Then Return 0
If gn.digit(%intsize - i) > 0 Then Exit Do
i += 1
Loop
Return %intsize - i
End Function
'--------------------------------------------------------------
Function genintseterror(gn As genint)
gn.error = TRUE
End Function
'--------------------------------------------------------------
Function genintshiftleft(gn As genint, nplaces As DWord)
Local sz, i, j As DWord
sz = genintgetsize(gn)
For i = 1 To sz
j = sz - i + 1
gn.digit(j + nplaces) = gn.digit(j)
Next
For i = 1 To nplaces
gn.digit(i) = 0
Next
End Function
'--------------------------------------------------------------
Function genintadd(a As genint, b As genint, c As genint)
Local i As DWord
Local s, v, k As Byte
Local asize, bsize, maxsize
Local temp As genint
asize = genintgetsize(a)
bsize = genintgetsize(b)
maxsize = asize
If bsize > maxsize Then maxsize = bsize
genintzero(temp)
k = 0
For i = 1 To maxsize + 1
s = a.digit(i) + b.digit(i) + k
v = Mod(s, 10)
k = s \ 10
temp.digit(i) = v
Next
For i = 1 To %intsize
c.digit(i) = temp.digit(i)
Next
End Function
'--------------------------------------------------------------
Function genintmult(a As genint, b As genint, c As genint)
Local i, j As DWord
Local p, v, k As Byte
Local asize, bsize, tsize As DWord
Local temp As genint
genintzero(c)
genintzero(temp)
asize = genintgetsize(a)
bsize = genintgetsize(b)
tsize = asize + bsize
If tsize > %intsize Then
genintseterror(c)
Return
EndIf
For i = 1 To asize
k = 0
For j = 1 To bsize + 1
p = a.digit(i) * b.digit(j) + k
v = Mod(p, 10)
k = p \ 10
temp.digit(j) = v
Next
genintshiftleft(temp, i - 1)
genintadd(c, temp, c)
genintzero(temp)
Next
End Function
' output --------------------------------------------------------------------------------------------
.
.
5
4
3
2
elapsed time = 448 seconds
200 factorial:
+7886578673647905035523632139321850622951359776871732632947425332443594499634033
42920304284011984623904177212138919638830257642790242637105061926624952829931113
46285727076331723739698894392244562145166424025403329186413122742829485327752424
24075739032403212574055795686602260319041703240623517008587961789222227896237038
97374720000000000000000000000000000000000000000000000000
C:\Users\root\Desktop\NEW THIN>