Android Question GroupingCharacter in B4XFormatter

Cadenzo

Active Member
Licensed User
Longtime User
First time I try the B4XFormatter. I need to format numbers like this:
5 -> 0.005
120 -> 0.120
1250 -> 1.250
MinimumIntegers is working but the effect of GroupingCharacter I cannot see
B4X:
Dim formatter As B4XFormatter : formatter.Initialize
formatter.GetDefaultFormat.GroupingCharacter  = "."
formatter.GetDefaultFormat.MinimumIntegers = 4
Log(formatter.Format(number))

Is it also possible to format numbers in groups of 4 integers like 12345678 -> 1234 5678?
 

emexes

Expert
Licensed User
B4X:
Dim formatter As B4XFormatter
formatter.Initialize
formatter.GetDefaultFormat.GroupingCharacter  = "."
formatter.GetDefaultFormat.MinimumIntegers = 4

Dim TestNumbers() As Int = Array As Int(4, 14, 145, 1459, 14592, 1415926, 14159265)

For Each number As Int In TestNumbers
    Log(number & TAB & formatter.Format(number))
Next

Log output:
Waiting for debugger to connect...
Program started.
4          0004
14         0014
145        0145
1459       1.459
14592      14.592
1415926    1.415.926
14159265   14.159.265

Presumably your question is: where are the grouping separators for the first three numbers?

I agree that logically they should be there, but I can also see that it wasn't anticipated that Formatter was going to be used this way.

What are you actually formatting? Part numbers? Bank account numbers? Id numbers? Phone Numbers? "Numbers" like those that have other characters within them, are usually best stored as strings.

But if you *really* have to store them as numbers (Int or Long or Double) *and* format them in some special way, then best to whip up a function that does precisely what you want.
 
Last edited:
Upvote 0

Cadenzo

Active Member
Licensed User
Longtime User
Thank you for testing it! Yes, I was missing the effect of GroupingCharacter only with numbers < 1000. I am actually formatting numbers for the level of (music)content. 1.000 = after one year lessons, 0.500 after half a year. That's why I want the "." also if it is smaller than 1000. In this View the level is on the left down corners.

Because I need it only between 0.005 and 9.995 I helped me now with this:
Dim formatter As B4XFormatter : formatter.Initialize
formatter.GetDefaultFormat.MinimumFractions = 3
formatter.GetDefaultFormat.MaximumFractions = 3
Log(formatter.Format(level / 1000))
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
I am actually formatting numbers for the level of (music)content. 1.000 = after one year lessons, 0.500 after half a year.
Because I need it only between 0.005 and 9.995 I helped me now with this:
Dim formatter As B4XFormatter : formatter.Initialize
formatter.GetDefaultFormat.MinimumFractions = 3
formatter.GetDefaultFormat.MaximumFractions = 3
Log(formatter.Format(level / 1000))

That is a much better way of doing it. ?

Note that you can change the decimal point to some different character (or even multiple characters ie string?)

And also the character used for padding out the fraction to MinimumFractions, so I guess you could make like 1.ooo and 0.5oo ?

Lol or even 1.?️?️?️ and 0.5?️?️ although I think those might be a case of taking a good idea too far...
 
Upvote 0

emexes

Expert
Licensed User
In this View the level is on the left down corners.

I had trouble finding the level in that video. Is the level the 0018308 in this screenshot? :

1665484556679.png
 
Upvote 0

emexes

Expert
Licensed User

A small digression...

Did you write that app? In B4A? There's some impressive stuff in it ? stuff way more advanced than just formatting a number,

and so I am wondering if there is more to your question than just converting 1234 to 1.234 ?

or maybe it was just late at night / early in the morning, and you were under pressure with not enough caffeine ?
 
Upvote 0

Cadenzo

Active Member
Licensed User
Longtime User
I had trouble finding the level in that video. Is the level the 0018308 in this screenshot? :
It is in the content list the number in left down corner (see picture) but also on other pages in the app the level is shown. So I wanted a better format. :)

Did you write that app? In B4A? There's some impressive stuff in it ? stuff way more advanced than just formatting a number,
Yes, it's my own, in B4A and B4i, thank you! :) My programming knowledge is very uneven (musician full-time). I am good at developing algorithms, e.g. to search for frequencies in sounds, but I lack a lot of basic knowledge. Because I didn't know e.g. JSON, I explored the protocol of the app communication with the server by myself. ?
 

Attachments

  • ScreenshotTheClar.JPG
    ScreenshotTheClar.JPG
    52.3 KB · Views: 83
Upvote 0

Cadenzo

Active Member
Licensed User
Longtime User
or maybe it was just late at night / early in the morning, and you were under pressure with not enough caffeine ?
No, it was evening and not enough alcohol ? Of course I could have built my own solution (as always), but I finally wanted to get to know the B4XFormatter and do it right for once.
 
Upvote 0

emexes

Expert
Licensed User
No, it was evening and not enough alcohol ?

When I look back at old code I can estimate within ±1 drink how much alcohol was behind the algorithm.

Of course I could have built my own solution (as always)

Well, rather than let it go to waste: here's how far I'd gotten before it became apparent that you only needed the one "." and that B4XFormatter was good enough.

Formatting function:
Sub skFormatter(Number As Long, MinDigits As Int, GroupSize As Int, GroupSeparator As String) As String
 
    Dim NumberString As String = Number    'Longs are good for 18 digits

    Do While NumberString.Length < MinDigits
        NumberString = "0" & NumberString    'keep adding until long enough'
    Loop
 
    For InsertSeparatorAt = NumberString.Length - GroupSize To 1 Step -GroupSize    'backwards, so we don't trip up over what's already been done
        Dim BeforeBit As String = NumberString.SubString2(0, InsertSeparatorAt)
        Dim AfterBit As String = NumberString.SubString(InsertSeparatorAt)
        NumberString =  BeforeBit & GroupSeparator & AfterBit    'insert group separator
    Next
 
    Return NumberString
 
End Sub
Test code:
Dim N As Long = 1
Do While N < 1000000000
    Log(N & TAB & skFormatter(N, 4, 3, "."))
    N = N * 7
Loop
Log output:
Waiting for debugger to connect...
Program started.
1           0.001
7           0.007
49          0.049
343         0.343
2401        2.401
16807       16.807
117649      117.649
823543      823.543
5764801     5.764.801
40353607    40.353.607
282475249   282.475.249
 
Upvote 0

Cadenzo

Active Member
Licensed User
Longtime User
When I look back at old code I can estimate within ±1 drink how much alcohol was behind the algorithm.
Really? ? My code always looks like 2-5 drinks to much

Yes, your code would solve it, but for my purpose this in post #3 is enough.

B4X:
Do While NumberString.Length < MinDigits
    NumberString = "0" & NumberString    'keep adding until long enough'
Loop

'or this
Dim NumberString As String = number, i0s As Int = MinDigits - NumberString.Length
If i0s > 0 Then NumberString = "0000000000".SubString(10 - i0s) & NumberString
 
Upvote 0

Cadenzo

Active Member
Licensed User
Longtime User
Code for formating numbers with free grouping.
B4X:
4    0.004    000,000,004    0000 0000 0004
14    0.014    000,000,014    0000 0000 0014
145    0.145    000,000,145    0000 0000 0145
1459    1.459    000,001,459    0000 0000 1459
14592    14.592    000,014,592    0000 0001 4592
1415926    1.415.926    001,415,926    0000 0141 5926
1.4159265E7    14.159.265    014,159,265    0000 1415 9265


B4X:
Dim TestNumbers() As Int = Array As Int(4, 14, 145, 1459, 14592, 1415926, 14159265)
   
For Each number As Int In TestNumbers
    Log(number & TAB & FormatNumberGrouping(number, 4, 3, ".") & TAB & FormatNumberGrouping(number, 9, 3, ",") & TAB & FormatNumberGrouping(number, 12, 4, " "))
Next

Sub FormatNumberGrouping(number As Long, mindigits As Int, GroupingDigits As Int, GroupingCharacter As String) As String
    Dim sNumber As String = number, i0s As Int = mindigits - sNumber.Length
    If i0s > 0 Then sNumber = "0000000000000000".SubString(16 - i0s) & sNumber
    Dim iLen As Int = sNumber.Length
    If GroupingDigits > 0 And GroupingDigits < iLen And GroupingCharacter <> "" Then
        Dim iCount As Int, iRest As Int = iLen Mod GroupingDigits
        If iRest > 0 Then iCount = GroupingDigits - iRest 'e.g. GroupingDigits = 3, Length = 4 -> Rest = 1, iCount = 2 -> first GroupingCharacter after 1 digit
        Dim sb As StringBuilder : sb.Initialize
        For i = 0 To iLen - 1
            If iCount > 0 And iCount Mod GroupingDigits = 0 Then sb.Append(GroupingCharacter)
            sb.Append(sNumber.CharAt(i))
            iCount = iCount + 1
        Next
        sNumber = sb.ToString
    End If
    Return sNumber
End Sub
 
Last edited:
Upvote 0

Cadenzo

Active Member
Licensed User
Longtime User
Sorry, there were some mistakes without testing. Now it is tested. Formatting numbers with free grouping.
 
Upvote 0
Top