Android Question “Solved” How to get the decimal part of a number?

Sergey_New

Well-Known Member
Licensed User
Longtime User
B4X:
Dim latitude As Double=43.123456
Dim m As Long
'...
' need to get the value m=123456
How to do it?
 

LucaMs

Expert
Licensed User
Longtime User
t would crash if latitude had no decimals.
have tested it in B4J and it does not crash

1717026206369.png
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
?
B4X:
    Dim latitude As Double= 43.123456
    Dim latitude As Double= 43
    Dim latitude As Double= .123456
    Dim m() As String = Regex.Split("\.", latitude)
    Log(IIf(m.Length = 1, 0, m(1)))
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
if you deal with numbers i think it is better to not convert it to string.
@Jeffrey Cameron gave you the correct answer in my opinion


it is better to stay with numbers when you deal with numbers.
 
Upvote 0

cklester

Well-Known Member
Licensed User
Would this not work?
B4X:
    Dim pVal As Double = 43.123456
    Dim pDec As Double = pVal - Floor(pVal)
    Log(pDec)

One of the problems with this approach is the rounding errors that can occur.

e.g.,

Example of Rounding Errors:
Sub AppStart (Args() As String)
    Log("Hello world!!!")
    Private num As Double = 31.987654321
    
    'inting
    Log(num.As(Int))
    Log(num-num.As(Int))

    'flooring
    Log(Floor(num))
    Log(num-Floor(num))

End Sub

resulting in

Hello world!!!
31
0.9876543210000008
31
0.9876543210000008

The best approach has to be converting it to a string first. That way, you avoid these slight rounding errors.
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
One of the problems with this approach is the rounding errors that can occur.

e.g.,

Example of Rounding Errors:
Sub AppStart (Args() As String)
    Log("Hello world!!!")
    Private num As Double = 31.987654321
   
    'inting
    Log(num.As(Int))
    Log(num-num.As(Int))

    'flooring
    Log(Floor(num))
    Log(num-Floor(num))

End Sub

resulting in



The best approach has to be converting it to a string first. That way, you avoid these slight rounding errors.

sorry but i dont understand.
you are dealing with doubles so why do you convert it to a int?

the best way to do it is just taking the double.
using floor to get the whole number before the decimal point and then substract the origin number with the whole number only.

as @Jeffrey Cameron did.
if you conert to string and start spliting the string you may get errors like

if there is no point in the number or if the phone instead of dot use comma "," you may get a crash.
 
Upvote 0

cklester

Well-Known Member
Licensed User
sorry but i dont understand.
you are dealing with doubles so why do you convert it to a int?

It's the same effect as flooring. Look closely at the results again...

31
0.9876543210000008
31
0.9876543210000008

The original number is 31.987654321. Both int() and floor() achieve the same result... and both are wrong.


the best way to do it is just taking the double.
using floor to get the whole number before the decimal point and then substract the origin number with the whole number only.

That's exactly what I showed in my example. And the result is wrong.
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
sorry but i dont understand.
you are dealing with doubles so why do you convert it to a int?

the best way to do it is just taking the double.
using floor to get the whole number before the decimal point and then substract the origin number with the whole number only.

as @Jeffrey Cameron did.
if you conert to string and start spliting the string you may get errors like

if there is no point in the number or if the phone instead of dot use comma "," you may get a crash.
To be honest, I didn't actually test this, that is why I phrased my reply as a question.

After running it in B4J it does appear that there is some conversion happening internally that is producing rounding errors. Honestly, 99% of my work is in VB.NET and I stopped using Double in favor of the Decimal datatype years ago and it does not suffer from this problem. When I ran this in B4J it came up with "0.12345599999999735" as the log result.

When I run this in VB.NET with the Decimal datatype, it produces the expected result:
B4X:
        'VB.NET code
        Dim pVal As Decimal = 43.123456
        Dim pDec As Decimal = pVal - Math.Floor(pVal)
        Debug.Print("Value is " & pDec)

        'output shows "Value is 0.123456"

So, given the inherent inaccuracies of the Double datatype, perhaps a string solution (albeit less efficient) is the best answer. I would probably format the value to ensure the value is the expected type:
B4X:
    Dim pVal As Double = 43.123456789
    Dim psVal As String = $"$0.9{pVal}"$
    Log(psVal.SubString(psVal.IndexOf(".")+1))
This shows the expected "123456789"
 
Last edited:
Upvote 0

ilan

Expert
Licensed User
Longtime User
It's the same effect as flooring. Look closely at the results again...
The original number is 31.987654321. Both int() and floor() achieve the same result... and both are wrong.




That's exactly what I showed in my example. And the result is wrong.
you are right i see it now, it is really weird
 
Upvote 0

epiCode

Active Member
Licensed User
B4X:
Sub DecimalPart ( dblstr As Double ) As String
    If dblstr-Floor(dblstr) = 0 Then Return "0" Else  Return Regex.Replace("^[\d].\.*",dblstr.As(String),"")
End Sub

- Returns full String
- no rounding issues
- returns "0" when there is no decimal part
- returns leading zeroes for example 21.0023 will return 0023 as string and not 23.
 
Upvote 0

Cosmo

Member
For positive values:
Convert the decimal value 'a' to an integer 'b'
Convert b to a decimal value
subtract a-b, the result is the decimal part of your number.

HTH, regards
 
Upvote 0

Raart

Member
IndexOf(".") is not suitable, because you could have a different symbol as decimal separator (possibly you would have to use a variable in which to put the system separator).

The following code should work:
B4X:
    Dim Num As Double = 2.36
'    Dim Num As Double = -2.36 ' to test negative numbers
    Dim IntPart As Int
    Dim DecimalPart As Double
   
    If Num >= 0 Then
        IntPart = Floor(Num)
    Else
        IntPart = Ceil(Num)
    End If
   
    DecimalPart = Abs(Num - IntPart)
    DecimalPart = Round2(DecimalPart, 2)
   
    Log("Original number: " & Num)
    Log("Int part: " & IntPart)
    Log("decimal part: " & DecimalPart)
Here the decimal part of a negative number results to be positive. This is incorrect.
-2 + 0.36 is not -2.36 but -1.64.
 
Upvote 0
Top