since puzzling around wit Project Euler (see also http://www.purebasic.fr/english/viewtopic.php?t=26985) I started programming arithmetic functions for strings...
I think, my implementation of Add(), Sub() and Mul() are not very fast (especially Mul) so maybe someone is able to optimize them! Or, someone is able to add some further functions, like Div(), Sqr() etc.
Code: Select all
#MaxPrecision=1000
Procedure.s Normalize(zahl.s)
If FindString(zahl,".",1)=0
zahl+"."
EndIf
ProcedureReturn zahl
EndProcedure
Procedure.s AddLeadingZeros(zahl.s,n)
ProcedureReturn LSet("",n,"0")+zahl
EndProcedure
Procedure.s AddTrailingZeros(zahl.s,n)
ProcedureReturn zahl+LSet("",n,"0")
EndProcedure
Procedure.s StripZeros(zahl.s)
Protected i=0
Protected komma=FindString(zahl,".",1)
If komma>2
While (i<komma-2) And (PeekB(@zahl+i)='0')
i+1
Wend
If i>0
zahl=Mid(zahl,i+1,#MAXSHORT)
komma-i
EndIf
EndIf
i=Len(zahl)-1
While (i>komma) And (PeekB(@zahl+i)='0')
i-1
Wend
zahl=Left(zahl,i+1)
ProcedureReturn zahl
EndProcedure
Procedure.s Add(a.s,b.s)
Protected i
Protected k
Protected s
Protected sum.s
a=Normalize(a)
b=Normalize(b)
Protected komm_a=FindString(a,".",1)
Protected komm_b=FindString(b,".",1)
If komm_a>komm_b : Swap a,b : Swap komm_a,komm_b :EndIf
a=AddLeadingZeros(a,komm_b-komm_a+1)
b=AddLeadingZeros(b,1)
Protected len_a=Len(a)
Protected len_b=Len(b)
If len_a<len_b
a=AddTrailingZeros(a,len_b-len_a)
Else
b=AddTrailingZeros(b,len_a-len_b)
EndIf
i=Len(a)
k=FindString(a,".",1)-1
s=0
sum=Space(i)
While i
i-1
If i=k
PokeB(@sum+i,'.')
Else
s+PeekB(@a+i)+PeekB(@b+i)-96
PokeB(@sum+i,s%10+48)
s=s/10
EndIf
Wend
ProcedureReturn StripZeros(sum)
EndProcedure
Procedure.s Mul(a.s,b.s)
Protected lena,lenb
Protected summe=0
Protected mul.s
Protected ziffer
a=Normalize(a)
b=Normalize(b)
Protected komm_a=FindString(a,".",1)
Protected komm_b=FindString(b,".",1)
a=Left(a,komm_a-1)+Mid(a,komm_a+1,#MAXSHORT)
b=Left(b,komm_b-1)+Mid(b,komm_b+1,#MAXSHORT)
lena=Len(a)
lenb=Len(b)
mul=LSet("0",lena+lenb,"0")
Repeat
lena-1
lenb=Len(b)
ziffer=(PeekB(@a+lena)-48)
If ziffer
Repeat
lenb-1
If lena+lenb<#MaxPrecision
summe=(PeekB(@a+lena)-48)*(PeekB(@b+lenb)-48)+(PeekB(@mul+lena+lenb+1)-48);Puffer(lena+lenb+1)
;Puffer(lena+lenb+1)=summe%10
;Puffer(lena+lenb)+summe/10
PokeB(@mul+lena+lenb+1,summe%10+48)
PokeB(@mul+lena+lenb,PeekB(@mul+lena+lenb)+summe/10)
EndIf
Until lenb=0
EndIf
Until lena = 0
ProcedureReturn StripZeros(Left(mul,komm_a+komm_b-2)+"."+Mid(mul,komm_a+komm_b-1,#MAXSHORT))
EndProcedure
Debug Mul("12345.6789","987654321.123456789")