I'll add this to inc/ParseUtil.inc as it seems to be the most appropriate file.
It supports right-align, left-align, left-trim, leading-spaces, trimmed-decimal, leading-zeros, trailing-zeros, and integers.
function format(double vp, string fp) as string
===============================================
' FORMAT STRING EXAMPLES
' ####
' 0000
' L###
' T####
' T00
' ####.##
' ####.00
' 000.##
' 000.000
'
string s
string f=fp
string sg=" "
int la
double v
int a=asc f
if a=0x4c then la=1 'L left align with space for '-' sign
if a=0x54 then la=2 'T left trim
if la then f=mid(f,2)
int de=instr(f,".")
int le=len(f)
int dp
int zl
int zr
int df
if asc(f,1)=48 then zl=1
if de
df=1
dp=le-de
if asc(f,de+1)=48 then zr=1
endif
'
'REJECT E FORMATS
s=str v
if instr(s,"E")
return s
endif
'
'DECIMAL SCALING
v=round(vp*pow(10,dp))
s=str v
'
'SIGN
if v<0
s=mid(s,2)
sg="-"
endif
'
int ls=len(s)+df
if ls<le
string c
if zl
c="0"
else
c=" "
endif
s=string(le-ls,c)+s 'PAD LEFT
elseif ls>le
return "?"+str(vp,5) 'SPACE TOO SMALL
endif
int i,j
'
'DECIMAL FORMATS
if de
s=left(s,de-1)+"."+mid(s,de)
'NAKED POINT
i=instr(1,s," .")
if i then mid(s,i)="0"
'
'LEADING DECIMAL ZEROS
i=de
do
i=instr(i+1,s," ")
if i then mid(s,i)="0" : continue do
exit do
loop
endif
'
'INSERT SIGN
i=0
do
i++
j=asc s,i
if j<>32
s=left(s,i-1)+sg+mid(s,i)
exit do
endif
loop
'
if de<>0 and zr==0
'REMOVE TRAILING DECIMAL ZEROS
i=len s
do
if i<1 then exit do
j=asc(s,i)
if j<>48
if j=46
mid(s,i)=" " 'REMOVE DECIMAL POINT
endif
exit do
endif
mid(s,i)=" " 'REMOVE 0
i--
loop
endif
'
'LEFT ALIGN OR TRIM
if la
ls=len s
s=ltrim s
if sg=" " and la=1
s=" "+s 'ALLOW SIGN ALIGN
endif
j=len s
s+=space(ls-j)
endif
return s
end function
Hi Charles,
I tried with this example... is the result right?
double x
x=367.055
Print Format(x, "##.####")
'result = 367.05500000000001
wait
Aha! Format rejected your number because it was too large for the format string. So the number was returned in its ugly and unprocessed form. This is probably a better option than throwing a run-time error. What do you think?
Sure, that might be fine, but could it also have just written "367.0550"?
If you understand my code you are welcome to fix it :)
an idea,
to fix better...
use console
function format(double vp, string fp) as string
===============================================
' FORMAT STRING EXAMPLES
' ####
' 0000
' L###
' T####
' T00
' ####.##
' ####.00
' 000.##
' 000.000
'
int neg
if vp<0 then neg=-1
string s
string f=fp
string ffp=fp
string sg=" "
int la
double v
int a=asc f
if a=0x4c then la=1 'L left align with space for '-' sign
if a=0x54 then la=2 'T left trim
if la then f=mid(f,2)
int de=instr(f,".")
int le=len(f)
int dp, zl, zr, df
int i
if asc(f,1)=48 then zl=1
if de
df=1
dp=le-de
if asc(f,de+1)=48 then zr=1
endif
'
'REJECT E FORMATS
s=str v
if instr(s,"E")
return s
endif
'
'DECIMAL SCALING
v=round(vp*pow(10,dp))
s=str v
'
'SIGN
if v<0
s=mid(s,2)
sg="-"
endif
'
int ls=len(s)+df
if ls<le
string c
if zl
c="0"
else
c=" "
endif
s=string(le-ls,c)+s 'PAD LEFT
elseif ls>le
string bb=right(vp,len(vp)-instr(vp,".")) 'parte destra del numero
'printl "bb=" bb
string aa=left(vp, instr(vp,".")-1) 'parte sinistra del numero
'printl "aa=" aa
int lenfp=len(right(ffp,len(ffp)-instr(ffp,".")))
'int lenbb=len(right(vp,instr(vp,".")))
int lenbb=len(bb)
'printl "lunghezza fp " lenfp
'printl "lunghezza bb " lenbb
'bb=bb & string(lenfp,"0")
if lenfp>0 then
if lenbb>lenfp then
if mid(bb,lenfp+1) > 5 then
if val(left(bb,lenfp))=val(string(lenfp,"9")) then aa = val((abs(aa) + 1) * neg)
for i=lenfp to 1 step -1 'verifica per tutta la parte decimale
int vbl=val(mid(bb,i,1))+1
'printl vbl
if vbl>9 then
mid(bb,i)="0"
else
mid(bb,i)=str(vbl) : exit for
end if
next i
'end if
end if
'bb=right(vp,lenfp)
end if
end if
bb=left(bb,lenfp)
printl bb
printl "numero inserito: " vp
printl "numero formato : " aa "." bb
return str(vp) 'SPACE TOO SMALL
endif
int i,j
'
'DECIMAL FORMATS
if de
s=left(s,de-1)+"."+mid(s,de)
'NAKED POINT
i=instr(1,s," .")
if i then mid(s,i)="0"
'
'LEADING DECIMAL ZEROS
i=de
do
i=instr(i+1,s," ")
if i then mid(s,i)="0" : continue do
exit do
loop
endif
'
'INSERT SIGN
i=0
do
i++
j=asc s,i
if j<>32
s=left(s,i-1)+sg+mid(s,i)
exit do
endif
loop
'
if de<>0 and zr==0
'REMOVE TRAILING DECIMAL ZEROS
i=len s
do
if i<1 then exit do
j=asc(s,i)
if j<>48
if j=46
mid(s,i)=" " 'REMOVE DECIMAL POINT
endif
exit do
endif
mid(s,i)=" " 'REMOVE 0
i--
loop
endif
'
'LEFT ALIGN OR TRIM
if la
ls=len s
s=ltrim s
if sg=" " and la=1
s=" "+s 'ALLOW SIGN ALIGN
endif
j=len s
s+=space(ls-j)
endif
return s
end function
double x
x=-368.05516
Printl Format(x, "##.####")
Printl Format(377.061, "##.####")
Printl Format(999.09996, "##.####")
Printl Format(-9.99996, "##.####")
wait
You could do this:
return "?"+str(vp,5) 'SPACE TOO SMALL
I tried to round up to the last digit...
if mid(bb,lenfp+1) > 5 then
if val(left(bb,lenfp))=val(string(lenfp,"9")) then aa = val((abs(aa) + 1) * neg)
...
We just need something simple that shows clearly in a tabulation, to indicate that the format should be adjusted.
Hi Charles,
I put your "format" function in the help, both under Console and under Files.
Cheers
Hi Nicola,
I've put the format function into ParseUtil.inc rather than console. (ParseUtil also includes StringUtil). It's a bit volatile since it is not core Oxygen.
Ok Charles,
will we have it available in the next update?
Yes soon. Not much change to core o2 but I'm reviewing a few of the inc files, and Peter Wirbelauer's window.inc and gdip.inc. There is also Grafide (an extension of Peroxide) which is intended for 3d graphics scripting.
I may also remove LeanLisp because I don't think this genre of coding is going anywhere except backwards in programming history.
Hi Charles,
great, we can't wait to have the new version. :)