Scala-native: java.lang.{Float, Double}::toString is inconsistent with JVM

Created on 9 Jan 2017  路  4Comments  路  Source: scala-native/scala-native

Scala JVM:

println(1.0) 
// prints "1.0"

Scala Native

println(1.0) 
// prints "1.000000"
bug javalib

Most helpful comment

Scala.js:

println(1.0)
// prints "1"

All 4 comments

Scala.js:

println(1.0)
// prints "1"

but why is consistency with JVM important here?

@RomanHargrave Given Scala's extremely thin spec, we generally consider deviations from the behavior of the reference implementation to be a bug. No matter how small the differences are. There are very few exceptions, they are listed in the docs.

This problem appears to be harder than it looks at first reading.

Analysis

Upon investigating the most promising prospect for a robust fix is to port
org.apache.harmony.luni.util.NumberConverter.

Now, you protest, "Scala, Java, & C have number converters all over the place.
"Lee, haven't you heard about the virtues of software reuse?".

It appears that Java JVM has a few quirks when it comes to displaying floating point numbers.
Gotta love it, must have made sense to someone.

For example,

@ Double.MaxValue.toString 
res0: String = "1.7976931348623157E308"

@ printf("%.16E", Double.MaxValue) 
1.7976931348623157E+308

Note that the JVM .toString has no + after the E.

I am not sure how many other quirks like this there are.
In particular where the transition from "normal" numbers to
scientific notation happens.

I futzed around with a couple of other existing format methods and
with C sprintf, specifying things like minimal digits and could not get anything to match the JVM output.
That is not to say that there is not a solution there, just that I could not find
it with a few days work.

Using another converter and then fixing up the result seems to be ugly, slow, and lead the the "Death of a thousand missing quirks!". A developer would be fixing quirks __long__ after their professional lifetime.

I hope to get back to this after I finish several PRs which are maturing. In case someone
takes the baton here before then:

Apparent Next Steps

  1. Write a test program to check the assumption that harmony luni.util.NumberConverter
    converts Float & Double to strings the same way that (at least one) JVM does. The
    cases of 0.0, 1.0, -1.0, {Float, Double}.MaxValue, MinValue, MinPositiveValue, all of those
    1 or 2 out of range, +/- NAN, probably powers of 10 up to 10^301, and probably a lot of others.)

  2. Decide the .scala file location & name . The simple but thing is to drop a new HarmonyFloatDoubleNumberConverter.scala in javalib/src/main/scala/java/lang. Probably a better
    thing to do would be to create a new location, javalib/src/main/scala/java/harmony/luni.util, or such.

  3. Port NumberConverter to Scala (Native).

  4. Run the tests above but this time between Scala Native & JVM. That is, given a faithful
    java baseline, was the port to Scala Native done accurately?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mkotsbak picture mkotsbak  路  4Comments

valencik picture valencik  路  3Comments

densh picture densh  路  4Comments

densh picture densh  路  5Comments

david-bouyssie picture david-bouyssie  路  5Comments