Interactive PowerBasic Forum

IT-Consultant: Charles Pegge => OxygenBasic => Topic started by: Charles Pegge on April 12, 2023, 04:23:59 PM

Title: Format Function
Post by: Charles Pegge on April 12, 2023, 04:23:59 PM
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
Title: Re: Format Function
Post by: Nicola on April 13, 2023, 11:37:59 AM
Hi Charles,
I tried with this example... is the result right?

double x
x=367.055
Print Format(x, "##.####") 
'result = 367.05500000000001
wait
Title: Re: Format Function
Post by: Charles Pegge on April 13, 2023, 12:10:47 PM
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?
Title: Re: Format Function
Post by: Nicola on April 13, 2023, 03:31:38 PM
Sure, that might be fine, but could it also have just written "367.0550"?
Title: Re: Format Function
Post by: Charles Pegge on April 13, 2023, 04:31:14 PM
If you understand my code you are welcome to fix it :)
Title: Re: Format Function
Post by: Nicola on April 17, 2023, 08:31:15 PM
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
Title: Re: Format Function
Post by: Charles Pegge on April 18, 2023, 04:47:13 AM
You could do this:

    return "?"+str(vp,5) 'SPACE TOO SMALL
Title: Re: Format Function
Post by: Nicola on April 18, 2023, 08:53:15 PM
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)
...
Title: Re: Format Function
Post by: Charles Pegge on April 18, 2023, 10:32:38 PM
We just need something simple that shows clearly in a tabulation, to indicate that the format should be adjusted.
Title: Re: Format Function
Post by: Nicola on April 20, 2023, 12:05:16 PM
Hi Charles,
I put your "format" function in the help, both under Console and under Files.
Cheers
Title: Re: Format Function
Post by: Charles Pegge on April 20, 2023, 12:55:38 PM
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.
Title: Re: Format Function
Post by: Nicola on April 20, 2023, 02:54:07 PM
Ok Charles,
will we have it available in the next update?
Title: Re: Format Function
Post by: Charles Pegge on April 20, 2023, 07:40:46 PM
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.
Title: Re: Format Function
Post by: Nicola on April 21, 2023, 06:04:44 PM
Hi Charles,
great, we can't wait to have the new version. :)