I am evaluating PureBasic for which I have found good performance (speed two times VB), but some things are nor clear.
I ask information how to make a formated output on a file or a printer.
I find many keywords Write.... for the different variable type, with the limitation of a single variable output for every keywords, a situation which is much less flexible than that in VB where with the Print # statement all can be done in a single line with the option of the default variable spacing with the "," .
In VB the case of a precise formated output with the Format statement it is possible specify how a number must be written ( also in the scientific notetion) and with the TAB() and SPC() funcion define the position in the line.
After the examinatioin of the keyword in PureBasic I think that to have a formated ouput I need to conver the numeric data in a strings and assamble them according the required spacing in a string line and print it; but is not clear how the obtain a scientific output for a real number.
I ask also information for the differnce to have an output on a file or a printer.
I thak very much for every information you can supply to me.
Formated Output
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Formated Output
Using strings is the way in PB. However, 'C' probably has the best way, sprintf. You can use sprintf or similar in PB thanks to some outstanding work by other PB Users:
http://www.purebasic.fr/english/viewtop ... 12&t=41097
http://www.purebasic.fr/english/viewtop ... 12&t=32026
http://www.purebasic.fr/english/viewtop ... 12&t=41097
http://www.purebasic.fr/english/viewtop ... 12&t=32026
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
Re: Formated Output
Hi dadda,
I came kicking and screaming to PB from VB6 over a year ago and know how you feel!
True, PB doesn't have the Format$() function.
The file i/o is great, but string concatenation is same or slower than VB6.
There are string memory approaches that crank up the speed if you are inclined.
Here are some routines I use...
Edited per Trond's feedback...
I came kicking and screaming to PB from VB6 over a year ago and know how you feel!
True, PB doesn't have the Format$() function.
The file i/o is great, but string concatenation is same or slower than VB6.
There are string memory approaches that crank up the speed if you are inclined.
Here are some routines I use...
Code: Select all
Macro StrDX(x, ndecs, Wd, FillChar=" ", LR=R)
;Debug StrDX(x,2,6,"@") +"~"
;Debug StrDX(x,3,8,"@",L) +"~"
LR#Set(StrD(x, ndecs), Wd, Fillchar)
EndMacro
Procedure.s StrDe(X.d, numsd.i=6)
;Debug StrDE(1.23456e7, 4) ; " 12.35e+6" <-- fixed widths
;Debug StrDE(-1.23456e7, 4) ; "-12.35e+6" <-- and Exponent in multiples of 3
;Debug StrDE(0, 4) ; " 0" <-- 0 is simplified, not 0.000e+0
; IN:
; x = real number to be formatted.
; numsd = integer specifying total number of significant digits.
; "aa.bbbe+3" -> 2 + 3 = 5
; RETURN:
; string of x with numsd significant digits using engineering notation.
Protected.i Exp, Sgn
If X > 0
Sgn = ' '
ElseIf X < 0
Sgn = '-'
X * -1
Else ; Should fill " 000.000e+0", +1 for 'sign', +1 for '.', +3 for 'e+0'
ProcedureReturn RSet("0", numsd + 5)
EndIf
exp = Round(Log10(X),#PB_Round_Down)
If exp > 0
exp / 3 * 3
Else
exp = (-exp + 3) / 3 * (-3)
EndIf
X = X * Pow(10,-exp)
If X >= 1000
X / 1000
exp + 3
EndIf
If X >= 100
numsd - 3
ElseIf X >= 10
numsd - 2
Else
numsd - 1
EndIf
If numsd < 0
numsd = 0
EndIf
If exp < 0
ProcedureReturn Chr(sgn) + StrD(x, numsd) + "e" + Str(exp)
Else
ProcedureReturn Chr(sgn) + StrD(x, numsd) + "e+" + Str(exp)
EndIf
EndProcedure
Procedure.i StringToFile(txt$, oFile.s, Append.i=0)
Protected.i i, of
If Append
of = OpenFile(#PB_Any, oFile) ; open or create if non-existent
Else
of = CreateFile(#PB_Any, oFile) ; Create new file or delete contents of existing file
EndIf
If of ;And IsFile(of); overkill and slow to use
FileSeek(of, Lof(of)) ; jump to the end of the file (result of Lof() is used)
WriteData(of, @txt$, Len(txt$))
i = Lof(of)
CloseFile(of)
ProcedureReturn i
Else
MessageRequester("StringToFile","FAIL",#MB_ICONERROR)
ProcedureReturn 0
EndIf
EndProcedure
Procedure.s FileToStringC(inFile.s) ; See Trond's simplified/faster FileToString() in later posting.
; Purebasic forum: ts-soft
Protected.i inf, fmt, lng, br, *m
Protected.s txt
inf = ReadFile(#PB_Any, inFile)
If inf ;And IsFile(of); overkill and slow to use
Fmt = ReadStringFormat(inf)
lng = Lof(inf)
If lng
*m = AllocateMemory(lng)
If *m
br = ReadData(inf, *m, lng)
If br = lng
Txt = PeekS(*m, lng, fmt)
Else
txt = #NULL$
EndIf
FreeMemory(*m)
EndIf
EndIf
CloseFile(inf)
ProcedureReturn txt
Else
MessageRequester("FileToString",infile + " not ready.",#MB_ICONINFORMATION)
ProcedureReturn #NULL$
EndIf
EndProcedure
; Since PB Native StrD() command does not do exponents :(
Debug StrD(1.23456e7,2) +"~"
Debug StrD(1.23456e7,3) +"~"
; For Engineering notation...
Debug StrDE(1.23456e7, 4) +"~" ; " 12.35e+6" <-- fixed widths
Debug StrDE(-1.23456e7, 4)+"~" ; "-12.35e+6" <-- and Exponent in multiples of 3
Debug StrDE(0, 4) +"~" ; " 0" <-- 0 is simplified, not 0.000e+0
; Dropping the exponents, beware truncating your results!
Debug StrDX(1.23456e7,2,6,"@") +"~" ; "123456~"
Debug StrDX(1.23456e7,3,8,"@",L)+"~" ; "12345600~"
Debug StrDX(1.23456e7,3,12,"@",L)+"~" ; "12345600.000~"
Last edited by skywalk on Fri Feb 11, 2011 3:32 am, edited 2 times in total.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Re: Formated Output
Skywalk, are you sure your procedure StrDE() works properly? These outputs don't look right to me:
Here's one that works properly (let's not hope that supposition comes back to haunt me...
)
It's also slightly faster in my test, ignoring that the output differs.
Code: Select all
Debug StrDE(-54675.5)
Debug StrDE(25)

Code: Select all
Procedure.s StrDe(Num.d, SigDig.i = 6)
Protected NumSign.i = ' ', ExpSign.s = "+"
Protected Exponent.i
If Num < 0
NumSign = '-'
Num * -1
EndIf
If Num <> 0
While Num >= 10
Num / 10
Exponent + 1
Wend
While Num <= 1
Num * 10
Exponent + 1
ExpSign = "-"
Wend
EndIf
ProcedureReturn Chr(NumSign) + StrD(Num, SigDig-1) + "e" + ExpSign + Str(Exponent)
EndProcedure
Re: Formated Output
I also want to suggest an improvement for your StringToFile(). You use the function IsFile(), which is unnecessary. It's not wrong, but the Is<something>() functions are rather slow and never really needed except for debugging. Testing that the value of the variable "of" is not zero (which you're doing in the code) is sufficient.
Edit: And the same for FileToString.
I would also like to suggest a simpler alternative to FileToString(). It's simpler because it assumes the character encoding of the file is the same as your program (ascii or ucs2 depending on whether you compiled the program with unicode or not). But if it meets your needs it's simpler (and slightly faster in my tests):
Edit: And the same for FileToString.
I would also like to suggest a simpler alternative to FileToString(). It's simpler because it assumes the character encoding of the file is the same as your program (ascii or ucs2 depending on whether you compiled the program with unicode or not). But if it meets your needs it's simpler (and slightly faster in my tests):
Code: Select all
Procedure.s FileToString(inFile.s)
Protected File.i
Protected D.s
File = ReadFile(#PB_Any, inFile)
If File
D = Space(Lof(File))
ReadData(File, @D, Lof(File))
CloseFile(File)
ProcedureReturn D
EndIf
EndProcedure
Re: Formated Output
Hi Trond,Trond wrote:Skywalk, are you sure your procedure StrDE() works properly? These outputs don't look right to me:Code: Select all
Debug StrDE(-54675.5) Debug StrDE(25)
Thanks for verifying these!
Yes, the numbers are the same. Just displayed more efficiently.

I almost never use Scientific notation and I chastise programmers whenever I see it.

With Engineering notation, you can "drop" the exponent for an SI unit very simply.
e+3 = "k", e+6 = "M", e-6 = "u", etc.
This imparts more information for the same number sparing my weary brain from having to do the manipulations.
Code: Select all
; Using Engineering notation
Debug StrDE(-54675.5) ; "-54.6755e+3"
Debug StrDE(25) ; " 25.0000e+0"
; Using Scientific notation
Debug StrDE(-54675.5) ; "-5.46755e+4"
Debug StrDE(25) ; " 2.50000e+1"
I didn't understand why isFile() was required if I received a non-zero return from Read or Open or Create File()?
Thanks again, I'll edit the posting...
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum