Android Question number format exception

invocker

Active Member
log
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
** Activity (main) Resume **
*** Service (myservice) Create ***
** Service (myservice) Start **

34.9912109375
Error occurred on line: 68 (B4XMainPage)
java.lang.NumberFormatException: For input string: "35 Kb"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
at anywheresoftware.b4a.debug.RDebugUtils.numberCast(RDebugUtils.java:58)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:348)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:146)
at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:262)
at com.robloxi.client.b4xmainpage._sendfm(b4xmainpage.java:392)
at com.robloxi.client.myservice._str_newdata(myservice.java:1863)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:146)
at anywheresoftware.b4a.BA$2.run(BA.java:387)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6737)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:860)
java.lang.Exception: java.lang.NumberFormatException: For input string: "35 Kb"
** Receiver (starter) OnReceive **
The Starter service should never be started from a receiver.
** Service (starter) Start **
** Receiver (myservice) OnReceive **
** Service (myservice) Start **

code
B4X:
Sub FormatFileSize(Bytes As Float) As String
    Private Unit() As String = Array As String(" Byte", " Kb", " Mb", " Gb", " Tb", " Pb", " Eb", " Zb", " Yb")
    If Bytes = 0 Then
        Return "0 Bytes"
    Else
        Private Po, Si As Double
        Private I As Int
        Bytes = Abs(Bytes)
        I = Floor(Logarithm(Bytes, 1024))
        Po = Power(1024, I)
        Si = Bytes / Po
        Log(Si)
        Return NumberFormat(Si, 0, 1)  & " "& Unit(I)
    End If
End Sub
 
Solution
I use almost the same sub:

I use something entirely different, but there is method behind the madness. 🙃

I'm glad we're agreed on the uppercase B for byte cf lowercase b for bit. 🍻

Also, whilst I don't mind one way or the other, apparently the SI standard is to have a space between the number and the unit. Unless they've changed it, like they did with L for litres. 🤔

B4X:
Dim D As Double = Rnd(100, 1000)
For I = 1 To 10
    Log(D & " = " & NumberPrefixUnit(D, "", "B"))
    D = D * 8 + Rnd(100, 1000)
Next


Sub NumberPrefixUnit(N As Double, Separator As String, Unit As String) As String
 
    Dim L As Long = N
 
    If L < 0 Then
        Dim Sign As String = "-"
        L = -L
    Else
        Dim Sign As String = ""    'or "...

Serge Bertet

Active Member
Licensed User
I use almost the same sub:
B4X:
' Returns a human readable file size
Sub FormatFileSize(Bytes As Long, decimal As Int) As String
    Private Unit() As String = Array As String(" Byte", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB")
    If Bytes = 0 Then Return "0" & Unit(0)
    Private Po, Si As Double
    Bytes = Abs(Bytes)
    Private I As Int = Floor(Logarithm(Bytes, 1024))
    Po = Power(1024, I)
    Si = Bytes / Po
    Return NumberFormat(Si, 1, decimal) & Unit(I)
End Sub
and it is working well, your error is not here.
 
Upvote 0

emexes

Expert
Licensed User
I use almost the same sub:

I use something entirely different, but there is method behind the madness. 🙃

I'm glad we're agreed on the uppercase B for byte cf lowercase b for bit. 🍻

Also, whilst I don't mind one way or the other, apparently the SI standard is to have a space between the number and the unit. Unless they've changed it, like they did with L for litres. 🤔

B4X:
Dim D As Double = Rnd(100, 1000)
For I = 1 To 10
    Log(D & " = " & NumberPrefixUnit(D, "", "B"))
    D = D * 8 + Rnd(100, 1000)
Next


Sub NumberPrefixUnit(N As Double, Separator As String, Unit As String) As String
 
    Dim L As Long = N
 
    If L < 0 Then
        Dim Sign As String = "-"
        L = -L
    Else
        Dim Sign As String = ""    'or " " to do things the Microsoft way
    End If

    Dim Prefix As Int = 0
    Do While L > 10000
        L = (L + 500) / 1000
        Prefix = Prefix + 1
    Loop
 
    Dim PrefixLetter As String = " kMGTPEZY".CharAt(Prefix)
 
    Return Sign & L & Separator & PrefixLetter.Trim & Unit
 
End Sub

Log output:
638 = 638B
6082 = 6082B
49546 = 50kB
396497 = 396kB
3172118 = 3172kB
2.5377184E7 = 25MB
2.03018133E8 = 203MB
1.624145687E9 = 1624MB
1.2993165769E10 = 13GB
1.03945326282E11 = 104GB
 
Last edited:
Upvote 1
Solution

emexes

Expert
Licensed User
I'll change my sub it immediately :p

Note that it gets Trimmed on the way out so that you don't end up with that spurious space when the prefix is x1 ie no prefix.

I use .CharAt a lot. Ditto in PowerBasic with the similar ASC(string, index).

My main gripe is that Char is almost, but not quite, String. And so the usual String methods don't work on them directly, you have to do odd-looking stuff like:

("" & " kMGTPEZY".CharAt(Prefix)).Trim

to turn the Char into a String so that you can .Trim it directly.

That whiz-bang new .As(String) feature would probably achieve the same thing but more elegantly.
 
Upvote 0

emexes

Expert
Licensed User
I use .CharAt a lot. Ditto in PowerBasic with the similar ASC(string, index).

I just had a look in the program I was working on at lunchtime today:

1669215309634.png


and I figured if you liked the Prefix -> PrefixLetter translation, you'd probably appreciate the poor man's IsLowercaseLetter test on the second line.

Another task I often put it to is converting a number 0..15 into its hex digit ie "0123456789ABCDEF".CharAt(HexValue)
 
Upvote 0
Top