### Author Topic: Converting Floating Point Numbers into Text in ASM  (Read 7408 times)

0 Members and 1 Guest are viewing this topic.

#### Charles Pegge

• Global Moderator
• Hero Member
• Posts: 672
• User-Rate: +27/-1
##### Converting Floating Point Numbers into Text in ASM
« on: June 26, 2007, 04:01:04 PM »
The fformat function works about 3.5 to 7 times faster than STR\$ or FORMAT\$.
You can specify from 0 to 9 decimal places but this fformat function does not support E notation.

PowerBasic v8 supports extended precision floats but FreeBasic v0.16b does not, so the Freebasic example is shown with double precision.

For PowerBasic

UPDATE: Supporting up to 18 decimal places see next posting below. 10 Jan 2007

Code: [Select]
`'------------------------------------------------------------------------' fformat' Assembler function for converting floating point numbers to text'------------------------------------------------------------------------' 26 June 2007' Charles E V Pegge' Using PowerBasic 8x#COMPILE EXE#DIM ALL'-----------------------''  DIAGNOSIC FUNCTIONS  ''-----------------------'FUNCTION displayhex(s AS STRING) AS STRING DIM c AS LONG,i AS LONG, j AS LONG , l AS LONG: : c=0: i=0: j=3: l=LEN(s) DIM t AS STRING: t=CHR\$(13)+CHR\$(10)+SPACE\$(l*3.125 +1) DO  INCR i: IF i>l THEN EXIT DO  MID\$(t,j)=RIGHT\$("0"+HEX\$(ASC(s,i)),2):j=j+3:INCR c  IF c>15 THEN c=0:MID\$(t\$,j)=CHR\$(13)+CHR\$(10):j=j+2 LOOP FUNCTION=LEFT\$(t,j-1)END FUNCTIONFUNCTION displayoct(s AS STRING) AS STRING DIM c AS LONG ,i AS LONG, j AS LONG,l AS LONG c=0:i=0:j=3:l=LEN(s) DIM t AS STRING: t=CHR\$(13)+CHR\$(10)+SPACE\$(l*4.125 +1) DO  INCR i:IF i>l THEN EXIT DO  MID\$(t,j)=RIGHT\$("00"+OCT\$(ASC(s,i)),3):j=j+4:INCR c  IF c>15 THEN c=0:MID\$(t\$,j)=CHR\$(13)+CHR\$(10):j=j+2 LOOP FUNCTION=LEFT\$(t,j-1)END FUNCTIONFUNCTION fformat(BYVAL  v AS EXTENDED PTR, BYVAL d AS LONG, BYVAL s AS BYTE PTR) AS LONGASM'======================'!mov ebx,v             ' double precision value ptr!mov edx,s             ' work and output buffer ptr!mov eax,d             ' decimal places required!mov eax,[edx+eax*4+16]' lookup decimal places multiplier!mov [edx+12],eax      ' store the multiplier selected'======================'aa:                    ''fstcw [edx+60]        ' save copy of control word'fstcw [edx+64]        ' save another copy to alter''or dword ptr [edx+64], &hc00 ' set bits 10 & 11 to truncate reals'and dword ptr [edx+64], &hfffff3ff ' clear bits 10 & 11 for default rounding up'fldcw [edx+64]        ' load control word with new rounding rule'!fld qword ptr [ebx]   ' load double preciion!db &hdb               ' load extended precision!db &h2b               ' [ebx]'cmp dword ptr d,0     ' are ther decimal places'jz a1                 ' bypass multiplier if not!fimul dword ptr [edx+12] ' multiply by number of dplacesa1:'!fbstp  [edx]         ' store result in packed binary coded decimal!db &hdf               ' PB wont accept the above line so these are the opcodes!db &h32'fldcw [edx+60]        ' restore control word to previous setting'----------------------'!                      ' set up pointers!mov ebx,edx           ' dest pointer!add ebx,64            ' offset from base'----------------------'                       ' check if negative!mov al,[edx+9]        ' load sign byte!cmp al,&h80           ' check negative sign bit ?!mov al,32             ' assume not by loading space!jnz bb                '!mov al,45             ' ascii '-' if it is negativebb:                    '!mov [ebx],al          ' store the neg sign or space!inc ebx               ' next dest!mov ecx,8             ' number of packed bcd pairs'----------------------'!                      ' unpack bcd, most signficant digits firstcc:                    ' { do loop!mov al,[edx+ecx]      ' load bcd pair!mov ah,al             ' for upper!shr ah,4              ' reposition upper!and eax,&h0f0f        ' mask bcd bits!or eax,&h3030         ' add 48 for ascii numbers!mov [ebx],ah          ' dest upper!inc ebx               ' inc dest!mov [ebx],al          ' dest lower!inc ebx               ' inc dest!dec ecx               ' bcd pair down count!jge cc                ' } repeat!mov dword ptr [ebx],0 ' end marker quad null'jmp xit1              ' no-formatting test'----------------------''                      ' format:'      FORMAT          ' remove leading zeros'                      ' insert decimal point'                      ' nul byte termination'                      ' return length of string'----------------------'!mov ecx,18            ' number of digits!add edx,64            ' set up src pointer (base+64)!mov ebx,edx           ' dest pointer!add ebx,32            ' (offset= base+96)!                      ' set sign!mov al, [edx]         ' load src!inc edx               ' next src!cmp al,45 '           ' is it neg '-'!jnz e1                '!mov byte ptr [ebx],45 ' set '-' sign!inc ebx               ' next dest'----------------------'!                      ' strip leading zerose1:                    ' do {!                      ' check for decimal point placement!cmp ecx,d           '!jnz e11               '!mov byte ptr [ebx],48 ' set 0!inc ebx               ' dest!jmp wholenum          ' left of decimal placee11:                   '!cmp byte ptr [edx],48 ' is it 0 ?!jnz wholenum          ' to transfer!                      ' continuing zero skip loop!inc edx               ' src!dec ecx               ' digit down count!jg e1                 '  } repeat!jmp xit1              ' finish'----------------------'!                      ' before decimal pt loopwholenum:              ''cmp dword ptr d,0     ' any decimal points ?'jz qcopy              ' bypass if no decimal pointe2:                    ' { do!                      ' decimal point test!cmp ecx,d             '!jz decimalpt          ' exit for decimal point insertion!mov al,[edx]          ' transfer byte by byte!mov [ebx],al          '!inc edx               ' next src!inc ebx               ' next dest!dec ecx               ' digit count down!jg e2                 ' } repeat!jmp xit1              ' finish'----------------------'!                      ' decimal point onwarddecimalpt:             ' insert decimal point!mov byte ptr [ebx],46 ' decimal point ascii 46!inc ebx               ' next destqcopy:                 '!add ecx,ebx           ' ptr to end of number!inc ecx               ' offset by 1e24:                   ' { rapid transfer loop with 4 byte chunks!mov eax,[edx]         ' src!mov [ebx],eax         ' store dest incl end null quad!cmp eax,0             ' was it a null quad?!jz xit                ' then finish!add edx,4             ' else next src quad!add ebx,4             ' and next dest quad!jmp e24               ' } repeat'======================'xit:                   ' finishing procedures!mov ebx,ecx           ' to get length of numberxit1:                  '!mov byte ptr [ebx],0  ' set null boundary byte!sub ebx,s             ' calc offset from beginning of data!sub ebx,96            ' minus start of num offset!mov function,ebx      ' gives length of string (excluding null terminator byte)'======================'END FUNCTION'--------------------''  MAP OF WORKSPACE  ''--------------------''' 00..08  packed bcd result' 09      sign of packed bcd result' 10..11  unused' 12..15  selected fp multiplier' 16..59  multiplier lookup table (for decimal point)' 60 .63  original fpu control word' 64..67  temp storage for altered fpu control word' 64..82  unpacked decimal text' 83..95  unused' 96..127 formatted number text including null terminating bytes' length of  number text, excluding terminator is returned by the function.'--------''  MAIN  ''--------'FUNCTION PBMAIN()DIM fv AS EXTENDED    ' value to convertDIM rs AS STRING    ' workspaceDIM ps AS BYTE PTR  ' pointer to workspaceDIM le AS LONG      ' length of converted number stringDIM ss AS STRING    ' string copy of resultDIM sp AS STRING    ' to display resultsrs=STRING\$(128,CHR\$(0)): ps=STRPTR(rs)MID\$(rs,17)=MKL\$(1)+MKL\$(10)+MKL\$(1e2)+MKL\$(1e3)+MKL\$(1e4) _+MKL\$(1e5)+MKL\$(1e6)+MKL\$(1e7)+MKL\$(1e8)+MKL\$(1e9)'  test values 'fv=-123.636666666666'fv=5.12345678le=fformat(VARPTR(fv),8,ps):ss=MID\$(rs,97,le):ss=LEFT\$(ss,LEN(ss)-1)sp="" _+ "fformat: "+displayhex(rs)+\$CR _+ ""+\$CR _+ "Result: "+ss+\$CR _+""+\$CR'--------------''  TIME TRIAL  ''--------------'DIM t AS DOUBLE, tf AS DOUBLE, ts AS DOUBLEDIM i AS LONGt=TIMERFOR i=1 TO 100000le=fformat(VARPTR(fv),8,ps)NEXTtf=TIMER-tt=TIMERFOR i=1 TO 100000le=LEN(FORMAT\$(fv,8))NEXTts=TIMER-tsp=sp _+ "speed test using 100,000 conversions:"+\$CR _+ "fformat "+STR\$(tf)+\$CR _+ "format\$ "+STR\$(ts)+\$CR _+ "Speed factor "+STR\$(ts/tf)+\$CR _+ ""MSGBOX spEND FUNCTION`

Code: [Select]
`'------------------------------------------------------------------------' fformat' Assembler function for converting floating point numbers to text'------------------------------------------------------------------------' 26 June 2007' Charles E V Pegge' Using FreeBasic 0.16b'-----------------------''  DIAGNOSIC FUNCTIONS  ''-----------------------'function displayhex(s as string) as string dim as long c=0,i=0,j=3,l=len(s) dim as string t=chr\$(13)+chr\$(10)+space(l*3.125 +1) do  i+=1:if i>l then exit do  mid\$(t,j)=right\$("0"+hex\$(asc(s,i)),2):j+=3:c+=1  if c>15 then c=0:mid\$(t\$,j)=chr\$(13)+chr\$(10):j+=2 loop function=left\$(t,j-1)end functionfunction displayoct(s as string) as string dim as long c=0,i=0,j=3,l=len(s) dim as string t=chr\$(13)+chr\$(10)+space(l*4.125 +1) do  i+=1:if i>l then exit do  mid\$(t,j)=right\$("00"+oct\$(asc(s,i)),3):j+=4:c+=1  if c>15 then c=0:mid\$(t\$,j)=chr\$(13)+chr\$(10):j+=2 loop function=left\$(t,j-1)end functionfunction fformat(byval  v as double ptr, byval d as long, byval s as byte ptr) as longasm'======================' mov ebx,[v]           ' double precision value ptr mov edx,[s]           ' work and output buffer ptr mov eax,[d]           ' decimal places required mov eax,[edx+eax*4+16]' lookup decimal places multiplier mov [edx+12],eax      ' store the multiplier selected'======================'aa:                    ''fstcw [edx+60]        ' save copy of control word'fstcw [edx+64]        ' save another copy to alter''or dword ptr [edx+64], &hc00 ' set bits 10 & 11 to truncate reals'and dword ptr [edx+64], &hfffff3ff ' clear bits 10 & 11 for default rounding up'fldcw [edx+64]        ' load control word with new rounding rule fld qword ptr [ebx]   ' load double preciion'fld xword ptr [ebx]   ' load extended precision'cmp dword ptr [d],0   ' are ther decimal places'jz a1                 ' bypass multiplier if not fimul dword ptr [edx+12] ' multiply by number of dplacesa1: fbstp [edx]           ' store result in packed binary coded decimal'fldcw [edx+60]        ' restore control word to previous setting'----------------------'                       ' set up pointers   mov ebx,edx           ' dest pointer add ebx,64            ' offset from base'----------------------'                       ' check if negative mov al,[edx+9]        ' load sign byte cmp al,&h80           ' check negative sign bit ? mov al,32             ' assume not by loading space jnz bb                ' mov al,45             ' ascii '-' if it is negativebb:                    ' mov [ebx],al          ' store the neg sign or space inc ebx               ' next dest mov ecx,8             ' number of packed bcd pairs'----------------------'                       ' unpack bcd, most signficant digits firstcc:                    ' { do loop mov al,[edx+ecx]      ' load bcd pair mov ah,al             ' for upper shr ah,4              ' reposition upper and eax,&h0f0f        ' mask bcd bits or eax,&h3030         ' add 48 for ascii numbers mov [ebx],ah          ' dest upper inc ebx               ' inc dest mov [ebx],al          ' dest lower inc ebx               ' inc dest dec ecx               ' bcd pair down count jge cc                ' } repeat mov dword ptr [ebx],0 ' end marker quad null'jmp xit1              ' no-formatting test'----------------------''                      ' format:'      FORMAT          ' remove leading zeros'          T           ' insert decimal point'                      ' nul byte termination'                      ' return length of string'----------------------' mov ecx,18            ' number of digits add edx,64            ' set up src pointer (base+64) mov ebx,edx           ' dest pointer add ebx,32            ' (offset= base+96)                       ' set sign mov al, [edx]         ' load src inc edx               ' next src cmp al,45 '           ' is it neg '-' jnz e1                ' mov byte ptr [ebx],45 ' set '-' sign inc ebx               ' next dest'----------------------'                       ' strip leading zerose1:                    ' do {                       ' check for decimal point placement cmp ecx,[d]           ' jnz e11               ' mov byte ptr [ebx],48 ' set 0 inc ebx               ' dest jmp wholenum          ' left of decimal placee11:                   ' cmp byte ptr [edx],48 ' is it 0 ? jnz wholenum          ' to transfer                       ' continuing zero skip loop inc edx               ' src dec ecx               ' digit down count jg e1                 '  } repeat jmp xit1              ' finish'----------------------'                       ' before decimal pt loopwholenum:              ''cmp dword ptr [d],0   ' any decimal points ?'jz qcopy              ' bypass if no decimal pointe2:                    ' { do                       ' decimal point test cmp ecx,[d]           ' jz decimalpt          ' exit for decimal point insertion mov al,[edx]          ' transfer byte by byte mov [ebx],al          ' inc edx               ' next src inc ebx               ' next dest dec ecx               ' digit count down jg e2                 ' } repeat jmp xit1              ' finish'----------------------'                       ' decimal point onwarddecimalpt:             ' insert decimal point mov byte ptr [ebx],46 ' decimal point ascii 46 inc ebx               ' next destqcopy:                 ' add ecx,ebx           ' ptr to end of number inc ecx               ' offset by 1e24:                   ' { rapid transfer loop with 4 byte chunks mov eax,[edx]         ' src mov [ebx],eax         ' store dest incl end null quad cmp eax,0             ' was it a null quad? jz xit                ' then finish add edx,4             ' else next src quad add ebx,4             ' and next dest quad jmp e24               ' } repeat'======================'xit:                   ' finishing proceduresmov ebx,ecx            ' to get length of numberxit1:                  ' mov byte ptr [ebx],0  ' set null boundary byte sub ebx,[s]           ' calc offset from beginning of data sub ebx,96            ' minus start of num offset mov [function],ebx    ' gives length of string (excluding null terminator byte)'======================'end asmend function'--------------------''  MAP OF WORKSPACE  ''--------------------''' 00..08  packed bcd result' 09      sign of packed bcd result' 10..11  unused' 12..15  selected fp multiplier ' 16..59  multiplier lookup table (for decimal point)' 60 .63  original fpu control word' 64..67  temp storage for altered fpu control word' 64..82  unpacked decimal text' 83..95  unused' 96..127 formatted number text including null terminating bytes' length of  number text, excluding terminator is returned by the function.'--------''  MAIN  ''--------'dim fv as double    ' value to convertdim rs as string    ' workspacedim ps as byte ptr  ' pointer to workspacedim le as long      ' length of converted number stringdim ss as string    ' string copy of resultrs=string\$(128,chr\$(0)): ps=strptr(rs)mid\$(rs,17)=mkl\$(1)+mkl\$(10)+mkl\$(1e2)+mkl\$(1e3)+mkl\$(1e4) _+mkl\$(1e5)+mkl\$(1e6)+mkl\$(1e7)+mkl\$(1e8)+mkl\$(1e9)'  test values 'fv=-123.636666666666'fv=5.12345678le=fformat(varptr(fv),8,ps):ss=mid\$(rs,97,le)print "fformat: "+displayhex(rs)printprint "Result: "+ssprint'--------------''  TIME TRIAL  ''--------------'dim as double t,tf,tsdim as long it=timerfor i=1 to 100000le=fformat(varptr(fv),8,ps)nexttf=timer-tt=timerfor i=1 to 100000le=len(str\$(fv))nextts=timer-tprint "speed test using 100,000 conversions:"print "fformat ",tfprint "str\$ ",tsprint "Speed factor ",ts/tfprintend`
« Last Edit: January 10, 2008, 01:23:57 PM by Charles Pegge »

#### Charles Pegge

• Global Moderator
• Hero Member
• Posts: 672
• User-Rate: +27/-1
##### Re: Converting Floating Point Numbers into Text: ASM update
« Reply #1 on: January 10, 2008, 01:20:37 PM »
This version will support up to 18 decimal places

PowerBasic
Code: [Select]
`'------------------------------------------------------------------------' fformat' Assembler function for converting floating point numbers to text'------------------------------------------------------------------------' Whole numbers accurate to 18 digits' Fractions to at least 15 digits precision' 18 decimal places' 10 January 2008' Charles E V Pegge' Using PowerBasic 8x#COMPILE EXE#DIM ALL'-----------------------''  DIAGNOSIC FUNCTIONS  ''-----------------------'FUNCTION displayhex(s AS STRING) AS STRING DIM c AS LONG,i AS LONG, j AS LONG , l AS LONG: : c=0: i=0: j=3: l=LEN(s) DIM t AS STRING: t=CHR\$(13)+CHR\$(10)+SPACE\$(l*3.125 +1) DO  INCR i: IF i>l THEN EXIT DO  MID\$(t,j)=RIGHT\$("0"+HEX\$(ASC(s,i)),2):j=j+3:INCR c  IF c>15 THEN c=0:MID\$(t\$,j)=CHR\$(13)+CHR\$(10):j=j+2 LOOP FUNCTION=LEFT\$(t,j-1)END FUNCTIONFUNCTION displayoct(s AS STRING) AS STRING DIM c AS LONG ,i AS LONG, j AS LONG,l AS LONG c=0:i=0:j=3:l=LEN(s) DIM t AS STRING: t=CHR\$(13)+CHR\$(10)+SPACE\$(l*4.125 +1) DO  INCR i:IF i>l THEN EXIT DO  MID\$(t,j)=RIGHT\$("00"+OCT\$(ASC(s,i)),3):j=j+4:INCR c  IF c>15 THEN c=0:MID\$(t\$,j)=CHR\$(13)+CHR\$(10):j=j+2 LOOP FUNCTION=LEFT\$(t,j-1)END FUNCTIONFUNCTION fformat(v AS EXTENDED, BYVAL d AS LONG, st AS STRING) AS LONG#REGISTER NONELOCAL s AS LONGs=STRPTR(st)ASM'======================'! mov ebx,v            ' double precision value ptr! mov edx,s            ' work and output buffer ptr'======================'aa:                    ''! fstcw [edx+60]      ' save copy of control word'! fstcw [edx+64]      ' save another copy to alter'! or dword ptr [edx+64], &hc00 ' set bits 10 & 11 to truncate reals'! and dword ptr [edx+64], &hfffff3ff ' clear bits 10 & 11 for default rounding up'! fldcw [edx+64]      ' load control word with new rounding rule'! fld qword ptr [ebx] ' load double preciion! db &hdb              ' load extended precision! db &h2b              ' [ebx]! mov eax,d            '! cmp eax,9            '! jl m1                '! fimul dword ptr [edx+52] ' pre multiply by 1e9! sub eax,9            'm1:                    '! cmp eax,0            '! jle a1               '! shl eax,2            '! add eax,edx          '! fimul dword ptr [eax+16] ' multiply by number of dplacesa1:                    ''! fbstp  [edx]        ' store result in packed binary coded decimal! db &hdf,&h32         ' PB wont accept the above line so these are the opcodes' fldcw [edx+60]       ' restore control word to previous setting'======================'!                      ' set up pointers! mov ebx,edx          ' dest pointer! add ebx,64           ' offset from base                       ' check if negative! mov al,[edx+9]       ' load sign byte! cmp al,&h80          ' check negative sign bit ?! mov al,32            ' assume not by loading space! jnz bb               '! mov al,45            ' ascii '-' if it is negativebb:                    '! mov [ebx],al         ' store the neg sign or space! inc ebx              ' next dest! mov ecx,8            ' number of packed bcd pairs! add edx,8'======================'!                      ' unpack bcd, most signficant digits firstcc:                    ' { do loop! mov al,[edx]         ' load bcd pair! dec edx              ' work backwards! mov ah,al            ' for upper! shr ah,4             ' reposition upper! and eax,&h0f0f       ' mask bcd bits! or eax,&h3030        ' add 48 for ascii numbers! mov [ebx],ah         ' dest upper! inc ebx              ' inc dest! mov [ebx],al         ' dest lower! inc ebx              ' inc dest! dec ecx              ' bcd pair down count! jge cc               ' } repeat! mov edx,s            ' restore pointer to base! mov dword ptr [ebx],0' end marker quad null' jmp xit1             ' no-formatting test'----------------------''                      ' format:'      FORMAT          ' remove leading zeros'                      ' insert decimal point'                      ' nul byte termination'                      ' return length of string'----------------------'! mov ecx,18           ' number of digits! add edx,64           ' set up src pointer (base+64)! mov ebx,edx          ' dest pointer! add ebx,32           ' (offset= base+96)                       ' set sign! mov al, [edx]        ' load src! inc edx              ' next src! mov byte ptr [ebx],al'! inc ebx              ' next dest'----------------------'                       ' strip leading zeros                       'e1:                    ' do {                       ' check for decimal point placement! cmp ecx,d            '! jnz e11              '! mov byte ptr [ebx],48' set 0! inc ebx              ' dest! jmp wholenum         ' left of decimal placee11:                   '! cmp byte ptr [edx],48' is it 0 ?! jnz wholenum         ' to transfer!                      ' continuing zero skip loop! inc edx              ' src! dec ecx              ' digit down count! jg e1                '  } repeat! jmp xit1             ' finish'----------------------'wholenum:              'e2:                    ' { do!                      ' decimal point test! cmp ecx,d            '! jz decimalpt         ' exit for decimal point insertion! mov al,[edx]         ' transfer byte by byte! mov [ebx],al         '! inc edx              ' next src! inc ebx              ' next dest! dec ecx              ' digit count down! jg e2                ' } repeat! inc ebx              '! jmp xit1             ' finish'----------------------'                       ' decimal point onwarddecimalpt:             ' insert decimal point! mov byte ptr [ebx],46' decimal point ascii 46! inc ebx              ' next dest! add ecx,ebx          ' ptr to end of number! inc ecx              ' offset by 1e24:                   ' { rapid transfer loop with 4 byte chunks! mov eax,[edx]        ' src! mov [ebx],eax        ' store dest incl end null quad! cmp eax,0            ' was it a null quad?! jz xit               ' then finish! add edx,4            ' else next src quad! add ebx,4            ' and next dest quad! jmp e24              ' } repeat'======================'xit:                   ' finishing procedures! mov ebx,ecx          ' to get length of numberxit1:                  '! mov edx,s            '! cmp byte ptr [edx+97],32 ' check for zero number! jg nz1               '! mov byte ptr [edx+97],48! add ebx,2            'nz1:                   ''! mov byte ptr [ebx],&h20  ' set null boundary byte! sub ebx,s            ' calc offset from beginning of data! sub ebx,97           '! mov function,ebx     ' gives length of string (excluding null terminator byte)'======================'! mov d,ebx' local st as string: st=string\$(d," ") ' test string loadingEND FUNCTION'--------------------''  MAP OF WORKSPACE  ''--------------------''' 00..08  packed bcd result' 09      sign of packed bcd result' 10..11  unused' 12..15  selected fp multiplier' 16..59  multiplier lookup table (for decimal point)' 60 .63  original fpu control word' 64..67  temp storage for altered fpu control word' 64..82  unpacked decimal text' 83..95  unused' 96..127 formatted number text including null terminating bytes' length of  number text, excluding terminator is returned by the function.'--------''  MAIN  ''--------'FUNCTION PBMAIN()DIM fv AS EXTENDED    ' value to convertDIM rs AS STRING  ' workspaceDIM ps AS BYTE PTR    ' pointer to workspaceDIM le AS LONG        ' length of converted number stringDIM ss AS STRING      ' string copy of resultDIM sp AS STRING      ' to display results' fformat workspce and lookup tablers=STRING\$(128,CHR\$(0)): ps=STRPTR(rs)MID\$(rs,17)=MKL\$(1)+MKL\$(10)+MKL\$(1e2)+MKL\$(1e3)+MKL\$(1e4) _+MKL\$(1e5)+MKL\$(1e6)+MKL\$(1e7)+MKL\$(1e8)+MKL\$(1e9)'Test values ''fv=-123.63666666666666666666666666'fv=5.12345678'fv=-12345678912345678.9'fv=-1'fv=0'fv= -123456789.123456789fv= -9.00000000000001le=fformat(fv,14,rs)ss=MID\$(rs,97,le)+\$CR+FORMAT\$(fv,15)sp="" _+ "fformat: "+displayhex(rs)+\$CR _+ ""+\$CR _+ "Result: "+\$CR+ss+\$CR _+"length: "+STR\$(le)+\$CR'--------------''  TIME TRIAL  ''--------------'DIM t AS DOUBLE, tf AS DOUBLE, ts AS DOUBLEDIM i AS LONGt=TIMERFOR i=1 TO 1000000le=fformat(fv,8,rs)NEXTtf=TIMER-tt=TIMERFOR i=1 TO 1000000le=LEN(FORMAT\$(fv,8))NEXTts=TIMER-tsp=sp _+ "speed test using 1000,000 conversions:"+\$CR _+ "fformat "+STR\$(tf)+\$CR _+ "format\$ "+STR\$(ts)+\$CR _+ "Speed factor "+STR\$(ts/tf)+\$CR _+ ""MSGBOX spEND FUNCTION`