双圆到小数点后1位的 kotlin: 从0.044999到0.1

我有一个双变量,这是 0.0449999,我想四舍五入到小数位 0.1

我正在使用 Kotlin,但 Java 解决方案也很有帮助。

val number:Double = 0.0449999

我试着用这两种方法得到小数点后1位:

  1. val solution = Math.round(number * 10.0) / 10.0
  2. val solution = String.format("%.1f", number)

问题是在这两种情况下我都得到了0.0,因为它将数字从 0.04舍入到 0.0。它不需要所有的小数和四舍五入。

我想获得0.1: 0.045 -> 0.05 -> 0.1

149494 次浏览

The BigDecimal rounding features several RoundingModes, 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.000010.1).

The .toBigDecimal() extension is available since Kotlin 1.2.

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.

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.

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

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()
}

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()
}

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

Try this way for two decimal value return as string

private fun getValue(doubleValue: Double): String {
return String.format(Locale.US, "%.2f", doubleValue)
}

In Kotlin I just use this function:

fun roundTheNumber(numInDouble: Double): String {


return "%.2f".format(numInDouble)


}

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

Use this extension function:

toBigDecimal(MathContext(3, RoundingMode.HALF_EVEN)).toPlainString()