Android Question Decimal problem figures in euros!

WebQuest

Active Member
Licensed User
Hi communities, I'm trying to write a solution that prints decimal places in euros. I can't find a solution that's common to all the numbers. Has anyone had the same problem? any advice is accepted. Thank you

Code:
Lprezzo.Text=Prezzo1
    If Lprezzo.Text.Length=3 Or Lprezzo.Text.Length=4 And  Lprezzo.Text.LastIndexOf2(0,4)=0  Then
        If Lprezzo.Text.Length=3 Then
            If Lprezzo.Text.LastIndexOf2(0,3)=0 Or Lprezzo.Text.LastIndexOf2(0,4)=0  Then
                Lprezzo.Text=Prezzo1&".00€"
            Else
                Lprezzo.Text=Prezzo1&"0€"
            End If
        End If
        If Lprezzo.Text.Length=4 Then
            Lprezzo.Text=Prezzo1&"€"
        End If
    Else
        Lprezzo.Text=Prezzo1&".00€"
    End If

The output is this with 5 different digits:
1.00€
10.00€
1000€
1000.00€
10000.00€
 

Midimaster

Active Member
Licensed User
I never use the EUR stored in a FLOAT variable as a base for programming. Better use CENTS instead. So it is better to store 20,60 EUR as 2060 CENTS. This resolves all problem with rounding and displaying money variables.

B4X:
Dim A as INT = 2060  ' 20,60 EUR
Dim B as INT = 1240  ' 12,40 EUR
Dim C as INT = A+B   ' 33,oo EUR

log ( Money(A) & " " & Money(B)  & " "  & Money(C))


Sub Money(value as INT) as STRING
    dim eur as INT = value/100
    dim cent as INT= Value Mod 100
    Return eur & "." & cent
End Sub

The function converts the values into strings, when needed for printing.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Don't try to format the numbers yourself.

Either use NumberFormat(2) or B4XFormatter:
B4X:
Dim formatter As B4XFormatter
formatter.Initialize
formatter.GetDefaultFormat.MaximumFractions = 2
formatter.GetDefaultFormat.MinimumFractions = 2
formatter.GetDefaultFormat.Postfix = "€"

For Each d As Double In Array(1, 10, 1000, 1.2)
    Log(formatter.Format(d))
Next
 
Upvote 0

emexes

Expert
Licensed User
I'd take a look at the numberformat or numberformat2 function
In particular, the concept of minimum and maximum number of decimal places: sometimes fractions-of-a-cent is reasonable, eg the price of electronic components when costing up a board for production.
 
Upvote 0

emexes

Expert
Licensed User
Better use CENTS instead.
B4X:
Dim A as INT = 2060  ' 20,60 EUR
Nice solution. I usually use Doubles for accounting, but I appreciate that it freaks some people out.

Note that Int cents max out at 20 million EUR, which ain't worth what it used to be. ✌
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Don't try to format the numbers yourself.

Either use NumberFormat(2) or B4XFormatter:
B4X:
Dim formatter As B4XFormatter
formatter.Initialize
formatter.GetDefaultFormat.MaximumFractions = 2
formatter.GetDefaultFormat.MinimumFractions = 2
formatter.GetDefaultFormat.Postfix = "€"

For Each d As Double In Array(1, 10, 1000, 1.2)
    Log(formatter.Format(d))
Next
I don't think this works well; probably a bug in B4XFormatData.

The decimal separator on my smartphone (italian language) is comma but B4XFormatData contains dot.

I have an old function (I have to check if I can use JavaObject instead of Reflector) which gets the default decimal separator:
B4X:
Public Sub getDecimalSeparator As Char
    Dim rfl As Reflector
    Dim nf As Object = rfl.RunStaticMethod("java.text.NumberFormat", "getInstance", Null, Null)
    rfl.Target = nf
    Dim sym As Object = rfl.RunMethod("getDecimalFormatSymbols")
    rfl.Target = sym
    Dim Separator As Char = rfl.RunMethod("getDecimalSeparator")
    Return Separator
End Sub

Running the Erel's code, with few lines added:
B4X:
Sub Test
    Dim formatter As B4XFormatter
    formatter.Initialize
    formatter.GetDefaultFormat.MaximumFractions = 2
    formatter.GetDefaultFormat.MinimumFractions = 2
    formatter.GetDefaultFormat.Postfix = "€"

    For Each d As Double In Array(1, 10, 1000, 1.2)
        Log(formatter.Format(d))
    Next

    Dim formatData As B4XFormatData = formatter.GetDefaultFormat
    LogColor(formatData, Colors.Blue) 'ignore

    LogColor("DecimalSeparator: " & getDecimalSeparator, Colors.Red)
End Sub

I get:
1595577927350.png
 
Last edited:
Upvote 0

Sandman

Expert
Licensed User
Longtime User
I never use the EUR stored in a FLOAT variable as a base for programming. Better use CENTS instead. So it is better to store 20,60 EUR as 2060 CENTS. This resolves all problem with rounding and displaying money variables.
While I have never personally worked with financial systems that require any high precision, I have understood that it's common to store the integer part of the money as one INT and the non-integer part as another INT. When used, or presented, they get combined. By storing them as two separate INTs, they never ever gets affected by rounding from the processor etc.
 
Upvote 0

emexes

Expert
Licensed User
While I have never personally worked with financial systems that require any high precision, I have understood that it's common to store the integer part of the money as one INT and the non-integer part as another INT.
I have, and I've never seen that. But I imagine it would be fun to roll your own such currency type, especially if the components end up with different signs.
 
Upvote 0

emexes

Expert
Licensed User
For currencies use BigDecimal values
I thought wtf, doesn't Java have a standard Currency type like pretty much every other compiled BASIC, but... heck, you're right. :oops:

ps. the :oops: is with reference to Java's omission, not to you being right.
 
Upvote 0
Top