Using a DecimalFormat is a perfectly good way to format a number.
However, you have a deeper issue here, which is that you should never use a Float or Double to store a value that needs to be exact, such as money.
That's because Floats and Doubles are stored as binary fractions, not decimal fractions. And just as you can't represent 1/3 exactly as a decimal fraction of any finite length (0.33333333333…), so you can't represent 1/10 exactly as a binary fraction (0.0001100110011…). So most of the decimal numbers you want to store will get approximated and rounded to the nearest binary fraction that can be stored. This isn't always obvious — when printing them out, they get rounded again to the nearest decimal fraction, and in many cases that ‘recovers’ the number you want — but there are many cases where it's noticeable, especially as the result of calculations.
You can see the effect in the Kotlin REPL:
>>> 0.1 + 0.2
res0: kotlin.Double = 0.30000000000000004
In this case, the binary fractions nearest to 0.1 and 0.2 sum to give a binary fraction that's nearer to 0.30000000000000004 than it is to 0.3.
(There are many existing questions on StackOverflow discussing this, such as here.)
So if you need your money values to be accurate (and you almost always do!), then you should store them some other way. For example, if you only ever need two decimal places (i.e. the number of paise), then simply store the number of paise as an integer. Or if you don't need to do any calculations, you could store the number as a string (which is otherwise a bad idea…).
However, the most general and flexible way in Kotlin (and Java) is to use BigDecimal. That uses decimal fractions internally to represent any decimal number exactly, to any precision you need, and you can easily do calculations and other manipulations.
In Java, using it is awkward and long-winded, but Kotlin's operator overloading makes it very natural, e.g.:
>>> val p1 = "0.1".toBigDecimal()
>>> val p2 = "0.2".toBigDecimal()
>>> p1 + p2
res3: java.math.BigDecimal = 0.3
DecimalFormat supports it too:
>>> java.text.DecimalFormat("#,##0.00").format(p1 + p2)
res4: kotlin.String! = 0.30
(Note: do not create a BigDecimal from a Float or Double, as the damage will already have been done. If you have an integer value, then start from an integer type such as Int or Long; otherwise, you'll need to start from a String to get an exact value.)
Answer from gidds on Stack OverflowHow do you round a number to N decimal places - Support - Kotlin Discussions
Problem with rounding a number.
math - Kotlin - How to eliminate decimals except the first two - Stack Overflow
Fixing floating-point arithmetics with Kotlin
I recently started to learn Kotlin. And for now I'm enjoying it. But I wanted to re-create some old tasks from C# because I wanted to get used to Kotlin. But one of the tasks demanded to leave 2 decimal numbers after the dot.
I wonder how can I use Math.round() in order to achive this. Because I personally don't think |"%.2f".Format(value)| it's a reliable way.The picture is me trying to figure it out. Thanks in advance.
val x = Math.floor(3.556 * 100) / 100 // == 3.55
Math.floor returns value that less than or equal to the argument and is equal to a mathematical integer.
In our case 3.556 * 100 = 355.6 and the floor would be 355.0, hence 355/100 = 3.55
You can set a rounding mode on the DecimalFormat:
DecimalFormat("#.##")
.apply { roundingMode = RoundingMode.FLOOR }
.format(3.556)
However, note that a Float does not actually store the number in decimal (base 10), and so it is not a suitable format for a number that you need to have a specific number of decimal places. When you convert it to a String, you may find that the number of decimal places has changed. To ensure a specific number of decimal places, you need BigDecimal.