Reputation: 4146
I have a Double variable that is 0.0449999
and I would like to round it to 1 decimal place 0.1
.
I am using Kotlin but the Java solution is also helpful.
val number:Double = 0.0449999
I tried getting 1 decimal place with these two solutions:
val solution = Math.round(number * 10.0) / 10.0
val solution = String.format("%.1f", number)
The problem is that I get 0.0 in both cases because it rounds the number from 0.04
to 0.0
. It doesn't take all decimals and round it.
I would like to obtain 0.1: 0.045 -> 0.05 -> 0.1
Upvotes: 126
Views: 216211
Reputation: 447
If you want a pure kotlin solution, that is usually required in KMP projects.
This extension method worked for me:
fun Double.round(decimals: Int): Double {
val factor = 10.0.pow(decimals)
return (this * factor).roundToInt() / factor
}
Upvotes: 2
Reputation: 2833
yet another extension function:
fun Number.roundDecimal(digits: Int): Double {
require(digits >= 0) { "Number of digits must be non-negative." }
val multiplier = 10.0.pow(digits.toDouble())
return round(this.toDouble().times(multiplier)) / multiplier
}
Upvotes: 0
Reputation: 1104
If You want pure Kotlin solution then you can use roundToInt()
method of Kolin
val result = ((number * 1000).roundToInt())/1000.0
Upvotes: 0
Reputation: 501
Use Kotlin Extension Function and then call where you need.
fun Double.roundTo(): Double = this.times(100.0).roundToInt() / 100.0
fun Long.roundTo(): Double = this.times(100.0).roundToInt() / 100.0
fun Float.roundTo(): Double = this.times(100.0).roundToInt() / 100.0
Example:
val amount = 156.26588
val roundAmount = amount.roundTo()
Log.d("Amount:" "$roundAmount") // Amount:156.26
Upvotes: 2
Reputation: 369
In Kotlin I just use this function:
fun roundTheNumber(numInDouble: Double): String {
return "%.2f".format(numInDouble)
}
Upvotes: 19
Reputation: 511
Use this extension function:
toBigDecimal(MathContext(3, RoundingMode.HALF_EVEN)).toPlainString()
Upvotes: -1
Reputation: 1361
For new comers
Using String.format for decimal precision can lead to problems for different languages.
Use the following code to convert Double to as many decimal places as you want.
val price = 6.675668
//to convert to 2 decimal places
totalTime = Math.round(totalTime * 100.0) / 100.00
// totalTime = 6.68
//to convert to 4 decimal places
totalTime = Math.round(totalTime * 10000.0) / 10000.00
// totalTime = 6.6757
Upvotes: 2
Reputation: 121
Try this way for two decimal value return as string
private fun getValue(doubleValue: Double): String {
return String.format(Locale.US, "%.2f", doubleValue)
}
Upvotes: 0
Reputation: 5973
Try this, its work for me
val number = 0.045
var filterUserPrice: String? = "%.2f".format(number)
Log.v("afterRoundoff"," : $filterUserPrice")// its print filterUserPrice is 0.05
Upvotes: 3
Reputation: 29844
1. Method (using Noelia's idea):
You can pass the number of desired decimal places in a string template and make the precision variable this way:
fun Number.roundTo(
numFractionDigits: Int
) = "%.${numFractionDigits}f".format(this, Locale.ENGLISH).toDouble()
2. Method (numeric, no string conversion)
fun Double.roundTo(numFractionDigits: Int): Double {
val factor = 10.0.pow(numFractionDigits.toDouble())
return (this * factor).roundToInt() / factor
}
One could create an overload for Float
as well.
Upvotes: 33
Reputation: 3854
I know some of the above solutions work perfectly but I want to add another solution that uses ceil and floor concept, which I think is optimized for all the cases.
If you want the highest value of the 2 digits after decimal use below code.
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat
here, 1.45678 = 1.46
fun roundOffDecimal(number: Double): Double? {
val df = DecimalFormat("#.##")
df.roundingMode = RoundingMode.CEILING
return df.format(number).toDouble()
}
If you want the lowest value of the 2 digits after decimal use below code.
here, 1.45678 = 1.45
fun roundOffDecimal(number: Double): Double? {
val df = DecimalFormat("#.##")
df.roundingMode = RoundingMode.FLOOR
return df.format(number).toDouble()
}
Here a list of all available flags: CEILING
, DOWN
, FLOOR
, HALF_DOWN
, HALF_EVEN
, HALF_UP
, UNNECESSARY
, UP
The detailed information is given in docs
Upvotes: 82
Reputation: 1153
An example of extension functions for Float and Double, round to n decimal positions.
fun Float.roundTo(n : Int) : Float {
return "%.${n}f".format(this).toFloat()
}
fun Double.roundTo(n : Int) : Double {
return "%.${n}f".format(this).toDouble()
}
Upvotes: 30
Reputation: 4146
Finally I did what Andy Turner
suggested, rounded to 3 decimals, then to 2 and then to 1:
Answer 1:
val number:Double = 0.0449999
val number3digits:Double = String.format("%.3f", number).toDouble()
val number2digits:Double = String.format("%.2f", number3digits).toDouble()
val solution:Double = String.format("%.1f", number2digits).toDouble()
Answer 2:
val number:Double = 0.0449999
val number3digits:Double = Math.round(number * 1000.0) / 1000.0
val number2digits:Double = Math.round(number3digits * 100.0) / 100.0
val solution:Double = Math.round(number2digits * 10.0) / 10.0
Result:
0.045 → 0.05 → 0.1
Note: I know it is not how it should work but sometimes you need to round up taking into account all decimals for some special cases so maybe someone finds this useful.
Upvotes: 170
Reputation: 803
Always beware of Locale!
With unspecified locale you can get occasional issue (e.g. with Portugies locale) such as
Fatal Exception: java.lang.NumberFormatException
For input string: "0,1"
1. Solution using DecimalFormat approach
fun Float.roundToOneDecimalPlace(): Float {
val df = DecimalFormat("#.#", DecimalFormatSymbols(Locale.ENGLISH)).apply {
roundingMode = RoundingMode.HALF_UP
}
return df.format(this).toFloat()
}
2. Solution using string format approach
fun Float.roundTo(decimalPlaces: Int): Float {
return "%.${decimalPlaces}f".format(Locale.ENGLISH,this).toFloat()
}
Upvotes: 13
Reputation: 147901
The BigDecimal
rounding features several RoundingMode
s, including those rounding up (away from zero) or towards positive infinity. If that's what you need, you can perform rounding by calling setScale
as follows:
val number = 0.0449999
val rounded = number.toBigDecimal().setScale(1, RoundingMode.UP).toDouble()
println(rounded) // 0.1
Note, however, that it works in a way that will also round anything between 0.0
and 0.1
to 0.1
(e.g. 0.00001
→ 0.1
).
The .toBigDecimal()
extension is available since Kotlin 1.2.
Upvotes: 65