Code: Select all
'==========================================================================
Sub Remove(Text As String,Char As String)
Var index = 0,asci=Asc(char)
For i As Integer = 0 To Len(Text) - 1
If Text[i] <> ASCi Then Text[index] = Text[i] : index =index+ 1
Next : Text = Left(Text,index)
End Sub
Sub insertdecimal(s As String,position As Long,char As String=".")
Dim As String part1,part2
If position > 0 And position <=Len(s) Then
part1=Mid(s,1,position-1)
part2=Mid(s,position)
s=part1+char+part2
End If
End Sub
Function smult(n As String,d As Long) As String 'multiply n by a single digit
Dim As String ans=String(Len(n)+1,"*")
Dim As Ubyte carry,main,temp
For z As Integer=Len(n)-1 To 0 Step -1
temp=(d)*(n[z]-48)+carry
main=temp Mod 10 +48
carry=temp\10
ans[z+1]=main
Next z
ans[0]=carry+48
Return Iif(Len(Ltrim(ans,"0")),Ltrim(ans,"0"),"0")
End Function
Function minus(Byval num1 As String,Byval num2 As String) As String 'subtract two strings
Static As Ubyte sm(0 To 19)={48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57}
Static As Ubyte sb(0 To 19)={1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0}
Dim As Integer bigger,swapflag
Dim sign As String * 1
Var lenf=Len(NUM1)
Var lens=Len(NUM2)
#macro finishup()
answer=Ltrim(answer,"0")
If answer="" Then Return "0"
If swapflag=1 Then Swap NUM1,NUM2
Return sign+answer
#endmacro
#macro compare()
If Lens>lenf Then bigger= -1:Goto fin
If Lens<lenf Then bigger =0:Goto fin
If NUM2>NUM1 Then
bigger=-1
Else
bigger= 0
End If
fin:
#endmacro
compare()
If bigger Then
sign="-"
Swap NUM2,NUM1
Swap lens,lenf
swapflag=1
End If
Var diff=lenf-lens
Dim As String answer=NUM1
Dim As Integer n
Dim As Ubyte takeaway,subtractcarry
subtractcarry=0
For n=lenf-1 To diff Step -1
takeaway= num1[n]-num2[n-diff]+10-subtractcarry
answer[n]=sm(takeaway)
subtractcarry=sb(takeaway)
Next n
If subtractcarry=0 Then:finishup():End If
If n=-1 Then:finishup():End If
For n=n To 0 Step -1
takeaway= num1[n]-38-subtractcarry
answer[n]=sm(takeaway)
subtractcarry=sb(takeaway)
If subtractcarry=0 Then Exit For
Next n
finishup()
End Function
Function isbigger(n1 As String,n2 As String) As Long 'is n1>n2
If Len(n1)>Len(n2) Then Return -1
If Len(n1)<Len(n2) Then Return 0
If n1>n2 Then
Return -1
Else
Return 0
End If
End Function
Function decmove(s As String) As Long
If Instr(s,".")=0 Then Return 0
Return Len(s)-Instr(s,".")
End Function
Sub adjustnumerator(d As String,dm As Long)
While decmove(d)<= dm
d+="0"
Wend
Var p=Instr(d,".")+dm
remove(d,".")
insertdecimal(d,p)
End Sub
Function divide(Byval n As String,Byval d As String,places As Long=10,f As String="") As String
Dim As Integer modstop,runcount
If f="mod" Then
If Len(n)<Len(d) Then Return n
If Len(n)=Len(d) Then
If n<d Then Return n
End If
modstop=Len(n)
End If
Dim As String sign
If Instr(n,"-") xor Instr(d,"-") Then sign="-"
n=Ltrim(n,"0"):d=Ltrim(d,"0")
remove(n,"-"):remove(d,"-")
If Instr(n,".")=0 Then n+="."
If Instr(d,".")=0 Then d+="."
Dim As String s(0 To 10)'to hold digit multiples
Dim As String ans
Dim As Long k,flag
Var dm=decmove(d)
adjustnumerator(n,dm)
n+=String(places-decmove(n),"0")
remove(d,".")
d=Ltrim(d,"0")
n=Ltrim(n,"0")
Dim As String top=Mid(n,1,1)
remove(top,".")
For m As Long=1 To Len(n)-1
If n[m]=Asc(".") Then flag=1:Continue For
For k =0 To 10 'range up the digits until the product > the numerator part
If k=10 Then
s(k)=d+"0"
Else
s(k)=smult(d,k)
End If
If isbigger(s(k),top) Then ans+=Str(k-1):runcount=runcount+1:Exit For
Next k
top=minus(top,s(k-1))
top+=Chr(n[m])'bring down the next digit
If flag=1 Then ans+=".":flag=0
If f="mod" Andalso runcount>=modstop Then
If top="" Then Return "0"
Return Mid(top,1,Len(top)-1)
End If
Next m
ans=Iif(Instr(ans,"."),Rtrim( Ltrim(ans,"0"),"."),ans)
If Len(ans)=0 Then ans="0"
Return sign+ ans
End Function
#define mod_(a,b) divide((a),(b),,"mod")
#define div_(a,b) iif(len((a))<len((b)),"0",divide((a),(b),0))
'===========================================================================
Type answer
As String quotient,remainder
End Type
Function longdivide(Byval numerator As String,Byval denominator As String) As answer
Dim As answer a
a.quotient=div_(numerator,denominator)
a.remainder=mod_(numerator,denominator)
Return a
End Function
#define Intrange(f,l) int(Rnd*(((l)+1)-(f))+(f))
Randomize
Print "test a few small numbers"
Dim As answer x
For n As Long=1 To 100
Var numerator=str(intrange(10,10000))
Var denominator=str(intrange(10,10000))
Print numerator;" / ";denominator
x=longdivide(numerator,denominator)
Print x.quotient; " remainder ";x.remainder
Print "check ";Val(x.quotient)*Val(denominator)+Val(x.remainder)
If Str(Val(x.quotient)*Val(denominator)+Val(x.remainder))<> numerator Then Print "ERROR":Sleep
Print "-----------"
Next
Print "press a key"
Sleep
Var numerator= "999999999999999999998888888888888888"
Var denominator="18446744073709551616"
Print numerator;" / ";denominator
x=longdivide(numerator,denominator)
Print x.quotient; " remainder ";x.remainder
print
numerator=string(2000,"9")
denominator=string(2000,"7")
x=longdivide(numerator,denominator)
Print x.quotient; " remainder ";x.remainder
print "Done"
Sleep