5

I was learning Kotlin and ran into this issue in Math class:

The java.lang.Math and kotlin.math are not compatible. This is for me a little bit awkward and confusing since Kotlin claims that it is 100% compatible with Java. Maybe this is only me who is feeling it is confusing, but I would like to hear community opinion to confirm if my feeling is correct.

The issue is the rounding of a number. Please observe the following simple Kotlin code:

fun main(args: Array<String>) {
val neg = -152.5
val kotlinAbsoluteValue = kotlin.math.abs(neg)
val javaAbsoluteValue = java.lang.Math.abs(neg)
println("Original Variable: $neg")
println("Absolute Value in Java: $javaAbsoluteValue")
println("Absolute Value in Kotlin: $kotlinAbsoluteValue")
println("Rounding kotlinAbsoluteValue in Java: ${java.lang.Math.round(kotlinAbsoluteValue)}")
println("Rounding kotlinAbsoluteValue in Kotlin: ${kotlin.math.round(kotlinAbsoluteValue)}")
println("Rounding javaAbsoluteValue in Java: ${java.lang.Math.round(javaAbsoluteValue)}")
println("Rounding javaAbsoluteValue in Kotlin ${kotlin.math.round(javaAbsoluteValue)}")
}

Output:

Original Variable: -152.5
Absolute Value in Java: 152.5
Absolute Value in Kotlin: 152.5
Rounding kotlinAbsoluteValue in Java: 153
Rounding kotlinAbsoluteValue in Kotlin: 152.0
Rounding javaAbsoluteValue in Java: 153
Rounding javaAbsoluteValue in Kotlin 152.0

I see that Java Math is rounding up to long value and Kotlin in contrast rounding down to kotlin.Double value. The implementation of Math classes in two different languages are different and wouldn't this cause confusion since they both target JVM?

Thanks

Dilshad Abduwali
  • 1,218
  • 7
  • 24
  • 38
  • 5
    Kotlin is 100% compatible with Java - but that means that if you use java.lang.Math in Java it will yield the same result as in Kotlin, not that different APIs (in this case java.lang.Math and kotlin.math) do exactly the same – msrd0 Mar 18 '18 at 13:47
  • @msrd0 Java and Kotlin don't round the same, as OP has pointed out. – IgorGanapolsky Aug 06 '20 at 15:13
  • 1
    @IgorGanapolsky No they don't, calling the same function in both languages yields the same result. Using different libraries might (and in this case will) behave differently – msrd0 Aug 06 '20 at 16:48

1 Answers1

5

The kotlin.math.round's documentation says:

Rounds the given value x towards the closest integer with ties rounded towards even integer.

So 152.5 is equally distant to 152 and 153, hence it is rounded to the closes even integer, i.e., 152.

On the other hand, Java's round says:

Returns the closest long [or int, depending on the supplied argument] to the argument, with ties rounding to positive infinity.

Looking at kotlin.math.round source code, that function is just delegating the operation to Java's Math.rint(x).

Sebastian
  • 6,895
  • 1
  • 35
  • 65
user2340612
  • 8,484
  • 4
  • 35
  • 61
  • 2
    ...and Java's round says: " with ties rounding to positive infinity." - so both results are fine and expected. – Sebastian Mar 18 '18 at 12:14
  • I read the doc as well, my point is, kotlin.math is rounding down it to 152.0(Double) and Java.lang.Math is rounding up to 153(long). this kind of inconsistant behaviour is confusion for me. – Dilshad Abduwali Mar 18 '18 at 12:14
  • 1
    @dhssa Kotlin also has `roundToInt`/`roundToLong` which uses Java's `round` method – Stefan Golubović Mar 18 '18 at 12:16
  • 2
    kotlin.math != java.lang.Math so kotlin.math.round may follow a different spec than java.lang.Math.round() - just because they have the same name, doesn't mean they cannot follow different specs. – Sebastian Mar 18 '18 at 12:16
  • 2
    as @Sebastian said, the APIs are different, so it's normal to expect a different behavior. In theory you could create your own `math` library that rounds to the closest odd integer and that would be fine as well, assuming it is documented properly – user2340612 Mar 18 '18 at 12:18
  • @Sebastian, Stefan , OK, thanks for the clarification, the explanation has resolved my confusion now. – Dilshad Abduwali Mar 18 '18 at 12:22
  • ~"**hence it is rounded to the closes even integer, i.e., 152.**". That is mathematically not correct. We learned that in grade school. – IgorGanapolsky Aug 06 '20 at 15:14
  • 1
    @IgorGanapolsky well, it depends on what you want to achieve. [Round half to even](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even) strategy is meant to minimise " the expected error when summing over rounded figures, even when the inputs are mostly positive or mostly negative" (from Wikipedia) – user2340612 Aug 06 '20 at 16:10