0

I need to use this value for price. So if the user writes 25, I want to load to the database 25.00 and if He writes 25.1, It should be 25.10. I don't know how to do that..actually that's what I do:

    EditText cost = findViewById(R.id.cost_single);

    // Temp var with the value of the Edit Text
    String costTemp = cost.getText().toString();


    if(descriptionPayment.length() > 0 && costTemp.length() > 0) {
        costPayment= Double.parseDouble(costTemp);
        Map<String, Object> payment = new HashMap<>();
        payment.put("cost", costPayment);
        payment.put("payed by", payedByText);
        db.collection("users").document(email).collection("Group").document(groupName)
                .collection("Payments").document(descriptionPayment)
                .set(payment)
        // rest of my code

How can I upload the double value with the 2 decimal places, even if the cost value hasn't any digits after point?

Nicola
  • 301
  • 3
  • 20

2 Answers2

2

tl;dr

new DecimalFormat( "##.00" )
.format(
    new BigDecimal( "25.1" ) 
)

25.10

BigDecimal

If you want an accurate representation of a decimal fraction, use the BigDecimal class. Always use BigDecimal for money matters.

BigDecimal bd = new BigDecimal( "25.1" ) ;

Floating-point

If you want to trade away accuracy for faster execution speed, use float/Float (32-bit) or double/Double. These use floating-point technology. So never use these for money or other contexts where accuracy is more important than performance.

Strings

Either way, remember your basic mathematics. The numbers 25.1 and 25.10 are the same number logically.

So what you are really asking is “How do I generate text to represent my number with two digits in the decimal fraction?”.

For the floating-point types, use DecimalFormat class.

DecimalFormat df = new DecimalFormat( "##.00" ) ;
String output = df.format( Double.parseDouble( "25.1" ) ;

See this code run live at IdeOne.com.

25.10

You can also localize. In some cultures such as the United States, a FULL STOP is used as the decimal separator, while in other places a COMMA is used. Search Stack Overflow for more info, as this has been covered.

Similar approach for generating strings that represent the value of a BigDecimal.

BigDecimal bd = new BigDecimal( "25.1" ) ;
DecimalFormat formatterBd = new DecimalFormat( "##.00" );
String outputBd = formatterBd.format( bd ) ;

See this code run live at IdeOne.com.

25.10

Rounding

Another related issue is rounding if you have more decimal digits in your number than you want to print. Search Stack Overflow as this has been addressed many many times.

About IdeOne.com

Regarding the links above to running code at IdeOne.com, the JVM in that site is rigged to use only one single locale, Locale.US. Attempts to specify other locales fail. So you cannot practice there the localization mentioned above.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • I wrote a better code for solving the link problem, when I tried to send it was marked as duplicate and even in the source question I could not send my answer! this link -> https://stackoverflow.com/questions/53623086/java-random-numbers-with-no-duplicates-for-a-lottery-using-methods-and-arrays – Mehdi Dec 05 '18 at 00:34
  • @BasilBourque so its ok if I save the value as a String? – Nicola Dec 05 '18 at 21:54
  • @Nicola String? Where? In Java you should only represent as a fractional monetary amount as a `BigDecimal` or as text, never in a floating-point type. In your database, the same – Use either a data type that can hold a number without floating-point technology, or as text as a last resort. I do not know Firebase, so I cannot advise, read their documentation regarding data types. For comparison, Postgres offers types for [arbitrary precision numbers](https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-NUMERIC-DECIMAL) suitable for money matters. – Basil Bourque Dec 05 '18 at 22:53
  • A workaround some folks use in a database not as robust as Postgres, or in a language without such a `BigDecimal` feature as offered in Java, is to **turn fractional amounts into integer amounts**. Ex: If tracking [USD](https://en.wikipedia.org/wiki/United_States_dollar) or [CAD](https://en.wikipedia.org/wiki/Canadian_dollar) amounts to the penny, then multiple money amounts by 100, and store as an integer type. I recommend this only as a last resort, because of course it is confusing and error-prone. Be sure to document thoroughly both in your db and in your app code if you go this route. – Basil Bourque Dec 05 '18 at 22:59
  • @BasilBourque yes, now I save the cost value in Firebase as a String type, not Float..but when I retrieve it and when I need to sum the cost of various payment, could I convert again to float for the addition?Or it's wrong? – Nicola Dec 06 '18 at 00:37
  • @Nicola Reread my Answer more carefully. Multiple times I said to use `BigDecimal`, never a data type involving floating-point such as `Float`, for matters where accuracy matters such as money. – Basil Bourque Dec 06 '18 at 01:22
  • @BasilBourque, ok thank you..Can I convert a String to a Big Decimal? – Nicola Dec 06 '18 at 08:18
  • @Nicola Are you pulling my leg? I show exactly that at least *3 times* in this Answer. – Basil Bourque Dec 06 '18 at 08:37
1

If you can use Big Decimal (that as mentioned in a comment it would be the right thing to do), then in this tutorial you can find the examples that you're looking for. The Big Decimal documentation can be found here instead. It all boils down to:

Bigdecimal bigdecimal = new Bigdecimal(25);
bigdecimal.setScale(2, BigDecimal.ROUND_HALF_EVEN) ;

Where the 2 says how many Decimal you should display and the rounding value says how to round the digits in case are more than 2 in this case. Please check the documentation as you might want to use a different rounding value.

AR1
  • 4,507
  • 4
  • 26
  • 42