Nice one, but if trying to use a precision higher than 6 it crashes.
See my implementation, using Pow slows things down a bit but not too much and you get rid of the array.
StrF2 has a issue with rounding though.
StrF3 behaves very closely to the original StrF but only up to around a precision of 6.
StrF can easily be tweaked to handle high numbers and very high precision (like 10 decimals after the . ) if you simply change all .l to .q
However any speed gains are lost as the original StrD is just as fast,
actually it seems that StrF and StrD are similar in speed, so if accuracy is wanted then StrD would be my advice.
If you know more or less what the input will be then it's not that hard to make speedier variants of PB's routines, but if you do not know what the input can be then you will find that PB's routines are much safer to use.
Apparently Fred knows his stuff
Code: Select all
EnableExplicit
DisableDebugger
Procedure.s StrD3(a.d,precision.l=6) ;Accurate up to a max precision of ?
Protected i.l,temp$,precmul.q,result$,n.q
If precision
precmul=Pow(10,precision)
If a=0.0
result$=RSet("0.",precmul,"0")
Else
n=a*precmul
temp$=StrQ(n)
result$=Left(temp$,Len(temp$)-precision)+"."+Right(temp$,precision)
EndIf
Else
If Not a
result$="0"
Else
result$=Str(a)
EndIf
EndIf
ProcedureReturn result$
EndProcedure
Procedure.s StrF3(a.f,precision.l=6) ;Accurate up to a max precision of 6
Protected i.l,temp$,precmul.l,result$,n.l
If precision
precmul=Pow(10,precision)
If a=0.0
result$=RSet("0.",precmul,"0")
Else
n=a*precmul
temp$=Str(n)
result$=Left(temp$,Len(temp$)-precision)+"."+Right(temp$,precision)
EndIf
Else
If Not a
result$="0"
Else
result$=Str(a)
EndIf
EndIf
ProcedureReturn result$
EndProcedure
Procedure.s StrF2(a.f,precision.l=6) ;Fast but has additional rounding errors compared to original?
Protected i.l,temp$,minus.l,result.l
precision=Pow(10,precision) ;Pow is used to avoid crash issue with higher precisions
If a<0
minus=1
a=-a
EndIf
i=a
If a<i
i-1
EndIf
temp$=Str(((a - i)*precision)+precision)
If minus
If precision>0
ProcedureReturn "-"+Str(i)+"."+Right(temp$,Len(temp$)-1)
Else
ProcedureReturn "-"+Str(i)
EndIf
Else
If precision>0
ProcedureReturn Str(i)+"."+Right(temp$,Len(temp$)-1)
Else
ProcedureReturn Str(i)
EndIf
EndIf
EndProcedure
#Tries = 500000
Define test$,i.l,time.l
time = GetTickCount_()
For i = 0 To #Tries
test$=StrF(-1234.5678910,6)
Next
MessageRequester("", Str(GetTickCount_()-time)+" "+test$)
time = GetTickCount_()
For i = 0 To #Tries
test$=StrF2(-1234.5678910,6)
Next
MessageRequester("", Str(GetTickCount_()-time)+" "+test$)
time = GetTickCount_()
For i = 0 To #Tries
test$=StrF3(-1234.5678910,6)
Next
MessageRequester("", Str(GetTickCount_()-time)+" "+test$)
time = GetTickCount_()
For i = 0 To #Tries
test$=StrD3(-1234.5678910,6)
Next
MessageRequester("", Str(GetTickCount_()-time)+" "+test$)
time = GetTickCount_()
For i = 0 To #Tries
test$=StrD(-1234.5678910,6)
Next
MessageRequester("", Str(GetTickCount_()-time)+" "+test$)