string math

General FreeBASIC programming questions.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: string math

Post by dodicat »

Thanks srvaldez, the divide is very fast.
Pity you couldn't get an inverse to spit out prime numbers, that would really be a numero uno.
Like Major Tom, they'd be wanting to know where you buy your shirts.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: string math

Post by srvaldez »

dodicat wrote: The long division mechanics are easy enough, getting a correct decimal place is fiddly.
it probably is because the result needs to be normalized, I just did a test and in 19995 divisions 8888 needed to be normalized
it's relatively easy when a floating point format is used, basically you shift the number left until there are no leading 0's
for each shift left you decrement the exponent
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: string math

Post by srvaldez »

dodicat wrote:Albert had the fastest multiplier, he used base 1e7.
We tested base 1e4 through base 1e9 but 1e7 was the fastest.
He had it in one intact function.
Pity he wasn't here to show the low down.
It was a grid type method at the core.
do you have that code?
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: string math

Post by dodicat »

Albert had multiplier_1,multiplier_4,multiplier_7, and multiplier_9

albert_reddit@yahoo.com

I have multiplier_7 intact(ish), although most of the stuff was on my old computer.
Albert and Richard worked on this stuff for months, Richard has his own method, but both grid multiplications.
The forum search is broken and has been for a long time, you cannot search for words inside code blocks, and nobody has bothered to repair it.
So the code will be hard to find, mostly in circles and squares.

Code: Select all


Function multiplier_7(Byref n1 As String, Byref n2 As String) As String
    Dim As String mul_num_1,mul_num_2
    Dim As String answer,outtext
    Dim As String int1,frac1,int2,frac2
    Dim As Ulongint dec,dec1,len1,len2
    Dim As String str1
    Dim As String sign1,sign2,outsign
    
    mul_num_1 = n1
    mul_num_2 = n2
    
    sign1 = Left(mul_num_1,1)
    If sign1 = "+" Or sign1 = "-" Then mul_num_1 = Mid(mul_num_1,2) Else sign1 = ""
    
    sign2 = Left(mul_num_2,1)
    If sign2 = "+" Or sign2 = "-" Then mul_num_2 = Mid(mul_num_2,2) Else sign2 = ""
    
    If (sign1 = sign2) Then outsign = ""
    If (sign1 <> sign2) Then outsign = "-"
    
    dec = Instr(1,mul_num_1,".")
    If dec > 0 Then 
        int1 = Left(mul_num_1,dec-1)
        frac1 = Mid(mul_num_1,dec+1)
    Else
        int1 = mul_num_1
        frac1 = ""
    End If
    
    dec = Instr(1,mul_num_2,".")
    If dec > 0 Then 
        int2 = Left(mul_num_2,dec-1)
        frac2 = Mid(mul_num_2,dec+1)
    Else
        int2 = mul_num_2
        frac2 = ""
    End If
    
    dec = Len(frac1)+Len(frac2)
    mul_num_1 = int1+frac1
    mul_num_2 = int2+frac2
    
    'swap numbers so that bigger number is mul_num_1 and smaller is mul_num_2
    If Len(mul_num_2) > Len(mul_num_1) Then Swap mul_num_1,mul_num_2
    If Len(mul_num_1) = Len(mul_num_2) Then 
        If Val(Left(mul_num_2,1)) > Val(Left(mul_num_1,1)) Then Swap mul_num_1,mul_num_2
    End If
    
    'make numbers equal multiple of 4 bytes
    Do
        str1 = Str(Len(mul_num_1)/4)
        dec1 = Instr(1,str1,".")
        If dec1 <> 0 Then mul_num_1 = "0" + mul_num_1
    Loop Until dec1 = 0
    Do
        str1 = Str(Len(mul_num_2)/4)
        dec1 = Instr(1,str1,".")
        If dec1 <> 0 Then mul_num_2 = "0" + mul_num_2
    Loop Until dec1 = 0
    
    'convert the numeric strings to use pointers
    'convert mul_num_1
    Dim As Ulong Ptr uip1 
    uip1 = Cptr(Ulong Ptr,Strptr(mul_num_1))
    Dim As Ulong val1
    For a As Long = 0 To Len(mul_num_1)-1 Step 4
        val1 = ((mul_num_1[a]-48)*1000) + ((mul_num_1[a+1]-48)*100) + ((mul_num_1[a+2]-48)*10) + (mul_num_1[a+3]-48)
        *uip1 = val1
        uip1+=1
    Next
    'convert the numeric strings to use pointers
    'convert mul_num_2
    Dim As Ulong Ptr uip2 
    uip2 = Cptr(Ulong Ptr,Strptr(mul_num_2))
    Dim As Ulong val2
    For a As Long = 0 To Len(mul_num_2)-1 Step 4
        val2 = ((mul_num_2[a]-48)*1000) + ((mul_num_2[a+1]-48)*100) + ((mul_num_2[a+2]-48)*10) + (mul_num_2[a+3]-48)
        *uip2 = val2
        uip2+=1
    Next
    
    'create accumulator
    answer = "0000" + String(Len(mul_num_1)+Len(mul_num_2),"0") 
    'dimension vars for the mul
    Dim As Long Ptr start1,stop1,start2,stop2 'use longint because the pointers go negative
    Dim As Ulong Ptr outplace
    Dim As Ulongint carry
    Dim As String result
    Dim As Long Ptr inc1,inc2
    Dim As Ulongint total
    Dim As Ulongint blockmul_num_1 = Len(mul_num_1)/4
    Dim As Ulongint blockmul_num_2 = Len(mul_num_2)/4
    Dim As Ulongint outblocks = Len(answer)/4
    
    'set initial accumulator place
    outplace = Cptr(Ulong Ptr , Strptr(answer)) + (outblocks - 1)
    'set initial pointers into mul_num_1 
    start1 = Cptr(Long Ptr , Strptr(mul_num_1))+(blockmul_num_1-1)
    stop1 =  Cptr(Long Ptr , Strptr(mul_num_1))+(blockmul_num_1-1)
    'set initial pointers into mul_num_2
    start2 = Cptr(Long Ptr , Strptr(mul_num_2))+(blockmul_num_2-1)
    stop2 =  Cptr(Long Ptr , Strptr(mul_num_2))+(blockmul_num_2-1)
    'zero the carry
    carry = 0
    
    'begin looping thru strings multiplying
    Do
        'set total to zero
        total = 0
        'we are going to be incrementing thru mul_num_2 while decrementing thru mul_num_1
        'working in opposite directions from start1 to stop1 and start2 to stop2
        'inc1 works from right to left in the mul_num_1 string
        'inc2 works from start2 to stop2 working from left to right, with start2 decrementing each loop.
        inc1 = start1
        inc2 = start2
        Do
            'total += ( (mul_num_2[inc2]-48) * (mul_num_1[inc1]-48) )
            total += *inc2 * *inc1
            '' print *inc2 * *inc1;" ";
            inc2 += 1
            inc1 -= 1
        Loop Until inc2 = stop2+1
        '' print
        total = total + carry
        carry = 0
        
        result = Str(total)
        carry = Val(Left(result,Len(result)-4))
        result = Right(result,4)
        *outplace = Val(result)
        
        outplace -= 1
        
        'each loop we need to decrement stop1
        'if stop1 goes negative we reset it to zero and decrement stop2
        stop1 -= 1
        If stop1 < Cptr(Long Ptr,Strptr(mul_num_1)) Then 
            stop1 += 1
            stop2 -=1
            If stop2 < Cptr(Long Ptr,Strptr(mul_num_2)) Then stop2 += 1
        End If
        'each loop we decrement start2 to the left
        start2 -= 1
        'if start2 goes negative we reset it to zero and decrement start1
        'start1 is the rightmost digit of mul_num_1 we need to multiply
        If start2 < Cptr(Long Ptr,Strptr(mul_num_2)) Then
            start2 += 1
            start1 -= 1
            If start1 < Cptr(Long Ptr,Strptr(mul_num_1)) Then start1 += 1 
        End If
        
    Loop Until outplace = Cptr(Ulong Ptr,Strptr(answer))+1
    
    'put in the carry at the end
    If carry > 0  Then *outplace = carry Else *outplace = 0
    
    'convert answer back to ascii
    For a As Ulongint = 1 To outblocks-1 Step 1
        val1 = *outplace
        outplace +=1
        outtext = outtext + Right("0000" + Str(val1),4)
    Next    
    
    'put in the decimal point
    outtext = Left(outtext,Len(outtext)-dec) + "." +  Mid(outtext,(Len(outtext)-dec)+1)
    'trim leading zeros
    outtext = Trim(outtext,"0") 'if multiplying by 1, we have a zero in front.
    outtext = outsign + Rtrim(outtext,".")
    Return outtext
    
End Function



Dim Shared As Ubyte _Mod_(0 To 99),_Div_(0 To 99)
For z As Long=0 To 99:_Mod_(z)=(z Mod 10+48):_Div_(z)=z\10:Next
    
    
    Function factorial(num As Long) As String
        Dim As String fact="1",a,b,c
        Dim As Ubyte n,carry,ai
        Dim As Long la,lb
        For z As Long=1 To num
            a=fact:b=Str(z):la=Len(a):lb=Len(b):c=String(la+lb,"0")
            For i As Long =la-1 To 0 Step -1
                carry=0:ai=a[i]-48
                For j As Long =lb-1 To 0 Step -1
                    n =ai*(b[j]-48)+(c[i+j+1]-48)+carry
                    carry =_Div_(n):c[i+j+1]=_Mod_(n)
                Next j
                c[i]+=carry
            Next i
            fact=Ltrim(c,"0")
        Next z
        Return fact
    End Function
    
    Dim As Double t
    print "please wait . . ."
    t=Timer
    Var f= factorial(6000)
    Print "time for factorial ";Timer-t
    t=Timer
    Var f2=multiplier_7(f,"6001")
    Print "time for multiply ";Timer-t
    Print "please wait, comparing"
    Print f2=factorial(6001)
    Print "Done"
    Sleep
    
     
I am going to have a break for a while so good luck with your project.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: string math

Post by srvaldez »

thank dodicat :)
Post Reply