meleduck
meleduck

Reputation: 103

Round decimals to the closest non zero digit in Kotlin

I am trying to print multiple doubles with different decimal points, I have search for a while but I cannot find the exact solution for my need.

Let me explain it as an example, so there are a few double variables here:

  1. 1.23
  2. 0.330
  3. 1.00
  4. 1.001

The result I want:

  1. 1.23
  2. 0.33 (unwanted 0 removed)
  3. 1 (unwanted 0 removed)
  4. 1.001

Is there any pre-developed syntax for this or do I have to make the algo myself?

My current solution:

fun Double.roundToLastDecimal(): Number {
    val num = this.toString().toDouble()
    return if (num % 1 == 0.0) {
        num.toInt()
    } else {
        num
    }
}

Upvotes: 2

Views: 1376

Answers (4)

cactustictacs
cactustictacs

Reputation: 19622

Double.toString() already does most of this for you - it just retains as many digits as necessary to distinguish the number from other doubles, so it'll strip the trailing zeroes.

The only issue is wanting 1.0 represented as 1, since that's technically an integer representation, not a double. You can write a function to take care of that case though:

// or a val with a get() to make the string representation a property
fun Double.roundToString() = when {
    toInt().toDouble() == this -> toInt()
    else -> this
}.toString()

Just FYI, if the number's small enough (less than 10¯³) toString() will produce scientific notation instead of listing all the digits with leading zeroes. If you want to handle those, you'll probably have to work with format strings, decide how much precision you want, etc.

Here's a way you can do that, with up to 10 digits of precision, and any trailing zeroes removed (and the decimal point itself, if it ends up at the end):

fun Double.roundToString() = "%.10f".format(this).trimEnd('0').trimEnd('.')

or using a regex if you're into that

fun Double.roundToString() = "%.10f".format(this).replace(Regex("\\.*0+$"), "")

Upvotes: 5

deHaar
deHaar

Reputation: 18588

I would use a simple extension function for Double, maybe like this:

fun Double.printMinimalRepresentation() {
    // check if the decimal places equal zero
    if (this % 1 > 0.0) {
        // if not, just print the number
        println(this)
    } else {
        // otherwise convert to Int and print
        println(this.toInt())
    }
}

Example values in a main function:

fun main() {
    var a: Double = 1.23
    var b: Double = 0.330
    var c: Double = 1.00
    var d: Double = 1.001

    a.printMinimalRepresentation()
    b.printMinimalRepresentation()
    c.printMinimalRepresentation()
    d.printMinimalRepresentation()
}

This prints

1.23
0.33
1
1.001

Please note that the conversion toInt() not only removes the unwanted zero but the obviously unwantet dot as well.

Upvotes: 2

QANew
QANew

Reputation: 52

Have you tried using the round function from the kotlin.math package?

import kotlin.math.round

Upvotes: -1

Viman Robert
Viman Robert

Reputation: 1

val value = 0.330

val res = (value * 100.0).roundToInt() / 100.0

Upvotes: 0

Related Questions