Grouping numbers: 1234 => 12,345
I got it 
I manage to put everything into 1 procedure.
But of course there's 2 procedures. 1 for Quads and 1 for Doubles.
I have to say that it is not a common programming-style.
I use some Reserved arguments to store some variables from one iteration to the next iteration.
It's often used in functional programming languages (but not in Basics).
So this time i think the result is very close to the Win32 one (about functionalities).
And only 12 clean lines per function

I manage to put everything into 1 procedure.
But of course there's 2 procedures. 1 for Quads and 1 for Doubles.
I have to say that it is not a common programming-style.
I use some Reserved arguments to store some variables from one iteration to the next iteration.
It's often used in functional programming languages (but not in Basics).
So this time i think the result is very close to the Win32 one (about functionalities).
And only 12 clean lines per function

Code: Select all
; StrNumQ(Number.q [, Grouping.l [, ThousandSep.s]])
; StrNumD(Number.d [, Grouping.l [, ThousandSep.s [, DecimalSep.s [, NumDigits.l]]]])
EnableExplicit
Procedure.s StrNumQ(Number.q, Grouping.l = 3, ThousandSep.s = ",", Reserved1.s = "", Reserved2.s = "", Reserved3.l = 0)
If Not Reserved3
ProcedureReturn StrNumQ(0, Grouping, ThousandSep, StrQ(Number), "", 1)
EndIf
If Not Reserved1 Or Reserved1 = "-"
ProcedureReturn Reserved1 + Reserved2
EndIf
If Reserved3 = 2
Reserved2 = ThousandSep + Reserved2
EndIf
ProcedureReturn StrNumQ(0, Grouping, ThousandSep, Left(Reserved1, Len(Reserved1)-Grouping), Right(Reserved1, Grouping) + Reserved2, 2)
EndProcedure
Procedure.s StrNumD(Number.d, Grouping.l = 3, ThousandSep.s = ",", DecimalSep.s = ".", NumDigits.l = 4, Reserved1.s = "", Reserved2.s = "", Reserved3.l = 0)
If Not Reserved3
ProcedureReturn StrNumD(0, Grouping, ThousandSep, "", 0, StringField(StrD(Number), 1, "."), DecimalSep + StringField(StrD(Number, NumDigits), 2, "."), 1)
EndIf
If Not Reserved1 Or Reserved1 = "-"
ProcedureReturn Reserved1 + Reserved2
EndIf
If Reserved3 = 2
Reserved2 = ThousandSep + Reserved2
EndIf
ProcedureReturn StrNumD(0, Grouping, ThousandSep, "", 0, Left(Reserved1, Len(Reserved1)-Grouping), Right(Reserved1, Grouping) + Reserved2, 2)
EndProcedure
Debug "StrNumQ()" ;{
Debug StrNumQ(1234567890)
Debug StrNumQ(123456789)
Debug StrNumQ(12345678)
Debug StrNumQ(1234567)
Debug StrNumQ(123456)
Debug StrNumQ(12345)
Debug StrNumQ(1234)
Debug StrNumQ(123)
Debug StrNumQ(12)
Debug StrNumQ(1)
Debug StrNumQ(0)
Debug StrNumQ(-1)
Debug StrNumQ(-12)
Debug StrNumQ(-123)
Debug StrNumQ(-1234)
Debug StrNumQ(-12345)
Debug StrNumQ(-123456)
Debug StrNumQ(-1234567)
Debug StrNumQ(-12345678)
Debug StrNumQ(-123456789)
Debug StrNumQ(-1234567890)
Debug ""
;}
Debug "StrNumD()" ;{
Debug StrNumD(1234567890.12345)
Debug StrNumD(123456789.12345)
Debug StrNumD(12345678.12345)
Debug StrNumD(1234567.12345)
Debug StrNumD(123456.12345)
Debug StrNumD(12345.12345)
Debug StrNumD(1234.12345)
Debug StrNumD(123.12345)
Debug StrNumD(12.12345)
Debug StrNumD(1.12345)
Debug StrNumD(0.12345)
Debug StrNumD(-1.12345)
Debug StrNumD(-12.12345)
Debug StrNumD(-123.12345)
Debug StrNumD(-1234.12345)
Debug StrNumD(-12345.12345)
Debug StrNumD(-123456.12345)
Debug StrNumD(-1234567.12345)
Debug StrNumD(-12345678.12345)
Debug StrNumD(-123456789.12345)
Debug StrNumD(-1234567890.12345)
Debug ""
;}
End
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
Thanks for the correction Shardik... cut & paste will get you every timeShardik wrote:@Paul:
Thank you for your fine API example. But in the second example there is a small mistake. In order to actually use your defined NUMBERFMT structure you have to provide the pointer to this structure instead of Null:

(that's what I get for trying to give 2 examples)
the fastest StrNumQ() i can do :
[EDIT] corrected.
Code: Select all
Procedure.s StrNumQ(NumberQ.q, Grouping.l = 3, ThousandSep.s = ",") ; 281
Protected GroupingNum.l = Pow(10, Grouping), NumberA.q, NumberS.s
While NumberQ / GroupingNum
NumberA = Abs(NumberQ)
NumberS = Str(NumberA % GroupingNum) + ThousandSep + NumberS
NumberQ / GroupingNum
Wend
NumberS = Str(NumberQ) + ThousandSep + NumberS
ProcedureReturn Left(NumberS, Len(NumberS) - 1)
EndProcedure
Debug "StrNumQ()" ;{
Debug StrNumQ(23487523465274653)
Debug StrNumQ(1234567890)
Debug StrNumQ(123456789)
Debug StrNumQ(12345678)
Debug StrNumQ(1234567)
Debug StrNumQ(123456)
Debug StrNumQ(12345)
Debug StrNumQ(1234)
Debug StrNumQ(123)
Debug StrNumQ(12)
Debug StrNumQ(1)
Debug StrNumQ(0)
Debug StrNumQ(-1)
Debug StrNumQ(-12)
Debug StrNumQ(-123)
Debug StrNumQ(-1234)
Debug StrNumQ(-12345)
Debug StrNumQ(-123456)
Debug StrNumQ(-1234567)
Debug StrNumQ(-12345678)
Debug StrNumQ(-123456789)
Debug StrNumQ(-1234567890)
Debug StrNumQ(-23487523465274653)
;}
Last edited by Flype on Thu Jan 18, 2007 9:24 am, edited 1 time in total.
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
> the fastest
and WORST StrNumD() you can do!
Check this out:
I've never seen such a strange number... 
and WORST StrNumD() you can do!

Check this out:
Code: Select all
Debug StrNumQ_D(23487523465274653)

PB 4.30
Code: Select all
onErrorGoto(?Fred)
YEHA!!! FINALLY! Now, I created a procedure with *only* 5 lines of code!!
Code: Select all
Procedure.s groupQuad(number.q, groupLen.l=3, separator.s=",")
Protected num.s=StrQ(number), currentPackage.s=Right(num, groupLen), currentLen.l=Len(num)-Len(currentPackage), result.s=currentPackage
If currentLen
result=groupQuad(ValQ(Left(num, currentLen)), groupLen, separator)+separator+result
EndIf
ProcedureReturn ReplaceString(result, "0"+separator, "-")
EndProcedure
For n=1 To 5
Debug groupQuad(1234567890, n)
Debug groupQuad(123456789, n)
Debug groupQuad(12345678, n)
Debug groupQuad(1234567, n)
Debug groupQuad(123456, n)
Debug groupQuad(12345, n)
Debug groupQuad(1234, n)
Debug groupQuad(123, n)
Debug groupQuad(12, n)
Debug groupQuad(1, n)
Debug groupQuad(0, n)
Debug groupQuad(-1, n)
Debug groupQuad(-12, n)
Debug groupQuad(-123, n)
Debug groupQuad(-1234, n)
Debug groupQuad(-12345, n)
Debug groupQuad(-123456, n)
Debug groupQuad(-1234567, n)
Debug groupQuad(-12345678, n)
Debug groupQuad(-123456789, n)
Debug groupQuad(-1234567890, n)
Debug ""
Next
PB 4.30
Code: Select all
onErrorGoto(?Fred)
yeah, nice, and recursive...
a little bit slower than my last one but pretty good.
finally my best :
fascinating...
a little bit slower than my last one but pretty good.
finally my best :
Code: Select all
Procedure.s StrNumQ(NumberQ.q, Grouping.l = 3, ThousandSep.s = ",")
Protected GroupingNum.l = Pow(10, Grouping), NumberS.s
While NumberQ / GroupingNum
NumberS = Str(IntQ(Abs(NumberQ)) % GroupingNum) + ThousandSep + NumberS
NumberQ / GroupingNum
Wend
NumberS = Str(NumberQ) + ThousandSep + NumberS
ProcedureReturn Left(NumberS, Len(NumberS) - 1)
EndProcedure
Procedure.s StrNumD(NumberD.d, Grouping.l = 3, ThousandSep.s = ",", DecimalSep.s = ".", NumDigits.l = 4)
ProcedureReturn StrNumQ(IntQ(NumberD), Grouping, ThousandSep) + DecimalSep + Left(StringField(StrD(NumberD), 2, "."), NumDigits)
EndProcedure
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
Here is shorter version of Paul's second API example:
It eliminates the need to define a complete NUMBERFMT structure only to get rid of the trailing two decimal places and the point/comma by using this API call:
And it automatically uses all the local settings defined in the user's windows OS like group separator character etc.
Code: Select all
Procedure.s FormatNumber(Number.Q)
Protected Buffer.S = Space(128)
GetNumberFormat_(#LOCALE_USER_DEFAULT, 0, StrQ(Number), 0, @Buffer, Len(Buffer))
ProcedureReturn Buffer
EndProcedure
SetLocaleInfo_(#LOCALE_USER_DEFAULT, #LOCALE_IDIGITS, @"0")
Debug FormatNumber(1234567890)
Code: Select all
SetLocaleInfo_(#LOCALE_USER_DEFAULT, #LOCALE_IDIGITS, @"0")
How to convert a integer-number (e. g. 12345) to a grouped integer WITHOUT decimals after the comma?Paul wrote:API version that uses system defaults for number formatting...Code: Select all
Procedure.s FormatNumber(Number.q) Buffer.s=Space(255) GetNumberFormat_(0,0,StrQ(Number),0,@Buffer,Len(Buffer)) ProcedureReturn Buffer EndProcedure
API version if you want to customize the formatting...Code: Select all
Procedure.s FormatNumber(Number.q) Buffer.s=Space(255) NF.NUMBERFMT\NumDigits=0 ;number of decimal places to use NF\Grouping=3 ;how many numbers before a seperator is used NF\lpDecimalSep=@"." ;decimal seperator character NF\lpThousandSep=@"," ;group seperator NF\NegativeOrder= 1 ;lookup LOCALE_INEGNUMBER for all options GetNumberFormat_(0,0,StrQ(Number),NF,@Buffer,Len(Buffer)) ProcedureReturn Buffer EndProcedure
I always get 12.345,00; but I don't want ,00 ...
PB 4.30
Code: Select all
onErrorGoto(?Fred)
it works well for me.
Code: Select all
Procedure.s FormatNumber1(Number.q)
Protected Format.NUMBERFMT, NumberStr.s = Space(255)
Format\Grouping = 3
Format\lpDecimalSep = @"."
Format\lpThousandSep = @","
Format\NegativeOrder = 1
GetNumberFormat_(#Null, #Null, StrQ(Number), @Format, @NumberStr, Len(NumberStr))
ProcedureReturn NumberStr
EndProcedure
Procedure.s FormatNumber2(Number.q)
Protected NumberStr.s = Space(255)
GetNumberFormat_(#Null, #Null, StrQ(Number), #Null, @NumberStr, Len(NumberStr))
ProcedureReturn NumberStr
EndProcedure
Debug FormatNumber1(-12345) ; -12,345 (using format - own settings)
Debug FormatNumber2(-12345) ; -12 345,00 (no format, it use locale settings - here french)
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
Currently, you're setting decimal point (.) and separator (,) manually. That's the problem: This should be done automatically to prevent mistakes caused by different conventions.
Germans use "," as decimal point, the rest of the world uses ".". It's the same thing for separators but swapped: Germany = ".", the others ","
I can't do this automatically when working with the structure.
Germans use "," as decimal point, the rest of the world uses ".". It's the same thing for separators but swapped: Germany = ".", the others ","
I can't do this automatically when working with the structure.
PB 4.30
Code: Select all
onErrorGoto(?Fred)
AND51 wrote: How to convert a integer-number (e. g. 12345) to a grouped integer WITHOUT decimals after the comma?
I always get 12.345,00; but I don't want ,00 ...
@AND51AND51 wrote: Currently, you're setting decimal point (.) and separator (,) manually. That's the problem: This should be done automatically to prevent mistakes caused by different conventions.
Germans use "," as decimal point, the rest of the world uses ".". It's the same thing for separators but swapped: Germany = ".", the others ","
I can't do this automatically when working with the structure.
Why didn't you try my above posted modified example of Paul's API solution? :roll:
I had the same problem and have it solved already...Shardik wrote: It eliminates the need to define a complete NUMBERFMT structure only to get rid of the trailing two decimal places and the point/comma by using this API call:

Oh, thank you very much.
But what about the SetLocale-Line? I left it out and it also works!
Actually, I want a procedure containing everything which is needed to convert my numbers; I don't want any calls outside this procedure.
But what about the SetLocale-Line? I left it out and it also works!
Actually, I want a procedure containing everything which is needed to convert my numbers; I don't want any calls outside this procedure.
PB 4.30
Code: Select all
onErrorGoto(?Fred)