Bug? Bug converting string to long?

tito

Member
Licensed User
Longtime User
Hi B4X Team,

did I something wrong or why does this code converting wrong?
wrong convert?:
    Dim SyncID As Long = 0
    Dim JobTagStr As String = "test_32589957803099334"
    Dim stemp2 As String = JobTagStr.SubString(JobTagStr.LastIndexOf("_")+1)
    If stemp2 <> "" And IsNumber(stemp2) Then
        SyncID = stemp2 'wrong convert : SyncID is 32589957803099336
    End If              '               instead of 32589957803099334

"stemp2" is still 32589957803099334
it is adding 2 and I dont know why :(
Investigated long time debugging to find the problem
the type "long" is up to 9,223,372,036,854,775,807 right?

I'm using B4A 10.70

Many thanks for support
Awesome B4A, did a lot with it already :)
 

William Lancee

Well-Known Member
Licensed User
Longtime User
I don't know why it doesn't work right. I haven't seen this before. You are doing nothing wrong.

B4X:
    'Long range -9223372036854775808 to 9223372036854775807
    Dim s As String = "32589957803099334"
    Dim x As Long = s
    Log(s & TAB & x)     'Log: 32589957803099334    32589957803099336

The same for negative numbers...

B4X:
    Dim s As String = "-32589957803099334"
    Dim x As Long = s
    Log(s & TAB & x)    '-32589957803099334    -32589957803099336

And clearly from string to number conversion...

B4X:
    Dim s As String = "-32589957803099334"
    Dim x As Long = s
    Log(s & TAB & (x + 2))    '-32589957803099334    -32589957803099334

And not just for your number, and not always out by 2.

B4X:
    Dim s As String = "325899578030993347"
    Dim x As Long = s
    Log(s & TAB & x)    '325899578030993347    325899578030993344
 
Last edited:

William Lancee

Well-Known Member
Licensed User
Longtime User
And more oddities:

B4X:
    Dim x As Long = 325899578030993334
    Log(x & TAB & NumberFormat2(x, 0, 0, 0, False))    '325899578030993334    325899578030993340
 

emexes

Expert
Licensed User
Most likely the 18-digit decimal number is being treated as a double-precision float, which "only" has (from memory) 53 bits of precision (~16 decimal digits) and then this is cast to Long by assignment to x.

What happens if you add L to end of decimal number? ie Dim x As Long = 325899578030993334L
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
There is no L suffix in B4X.

There is indeed a bug here. The parsing always goes through a double number.
For now, you can workaround it by casting the string to object:
B4X:
SyncID = stemp2.As(Object)
It will work in release mode and in debug mode when there are no breakpoints in the sub and the relevant code is "clean".

It it will be fixed.
 

Peter Simpson

Expert
Licensed User
Longtime User
B4X:
SyncID = stemp2.As(Object)
Hello @Erel, how does that work?
According to @tito's code stemp2 already has the correct value, it's when it is copied into SyncID that SyncID is still out by 2 but stemp2 is still 100% correct according post #1, or am I missing something pretty obvious (and no I've only had a cup of tea this morning). Let me fire up a laptop and test @tito's code with your .AS solution, I'm completely lost with your answer which is rare these days o_O

An easy temporary fix that should work would just be to use, until Anyware Software releases an update
B4X:
Dim SyncID As String 'Just for now

Or another solution would be to use the BigNumbers Library until this issue is fixed by Anywhere Software.
Not tested, just based on the code in post #1
B4X:
    Dim SyncID As BigInteger
    Dim JobTagStr As String = "test_32589957803099334"
    Dim stemp2 As String = JobTagStr.SubString(JobTagStr.LastIndexOf("_")+1)
    If stemp2 <> "" And IsNumber(stemp2) Then
        SyncID.Initialize(stemp2) 'SyncID should now be 32589957803099334
    End If
 

mcqueccu

Well-Known Member
Licensed User
Longtime User
Or another solution would be to use the BigNumbers Library until this issue is fixed by Anywhere Software.
Not tested, just based on the code in post #1
B4X:
    Dim SyncID As BigInteger
    Dim JobTagStr As String = "test_32589957803099334"
    Dim stemp2 As String = JobTagStr.SubString(JobTagStr.LastIndexOf("_")+1)
    If stemp2 <> "" And IsNumber(stemp2) Then
        SyncID.Initialize(stemp2) 'SyncID should now be 32589957803099334
    End If

I tested your code and it works - String it is until Anyware Software releases an update :cool:
 

Peter Simpson

Expert
Licensed User
Longtime User
The conversion between object to number properly handles this case. It is slightly different than the conversion between explicit string to number.
.AS didn't work with the example above, it was still out by 2, I tested it a few hours later.
 
Top