2

When I use doubles for computation in Python, formatting the output of those doubles gives back strings that look like this:

>>> v = 1 / 10.0
>>> v
0.1
>>> "%.25f" % v
'0.1000000000000000055511151'

However, when I do something similar with Scala, I get zeroes at the end:

scala> val v = 1 / 10.0
v: Double = 0.1

scala> "%.25f" format v
res0: String = 0.1000000000000000000000000

I would like to use Scala to output double-precision decimals with the same precision/rounding/whatever as Python, so that I can produce identical output from both the Scala and Python code. Does anyone know a way to do this?

Thanks!

Edit

I've done some experimentation, and this Java program seems to produce identical output to the Python code:

import java.math.BigDecimal;
public class Main {
    public static void main(String[] args) {
        double v1 = 1.0;
        double v2 = 10.0;
        double v3 = v1 / v2;
        BigDecimal bd1 = new BigDecimal(v3);
        System.out.println(String.format("%.25f", bd1));
    }
}

Created a similar program in Scala, but it doesn't work:

object Main extends App {
    val v1: Double = 1.0d
    val v2: Double = 10.0d
    val v3: Double = v1 / v2
    val bd1: BigDecimal = BigDecimal(v3)
    println("%.25f" format bd1)
}

Perhaps the best option for someone in my circumstance would be to include some plain-Jane Java code in the Scala project for the purposes of formatting. Will mark the question as answered.

bnsmith
  • 1,667
  • 19
  • 30
  • I'd go read the JVM and Python's spec for doubles. – pedrofurla Dec 08 '15 at 21:02
  • Try using `Float` instead of `Double`: `scala> "%.25f".format(1/10f) res16: String = 0.1000000014901161200000000 ` Note, that you won't be able to produce _identical_ output in any case, because the numbers you see after series of zeros are essentially garbage. – Dima Dec 08 '15 at 21:32
  • 2
    @Dima while one's perception of these digits as “garbage” is a matter of personal viewpoint, they are certainly reproducible. The `double` value `0.1` (the `double` number closest to 1/10) is unique, as is its decimal expansion, and this is what Python is showing. What Java is showing for that `double` is also uniquely determined, though by a different algorithm. – Pascal Cuoq Dec 08 '15 at 22:34

1 Answers1

3

Java and Scala give you the minimal decimal representation that converts back to the same double you started from. Python gives you the decimal digits of the exact rational number represented by the double you have. These two definitions usually differ radically after the 17th significant digit. In fact, the first one never uses more than 17 significant digits, whereas the second one can have about 750.

In order to obtain the same string of decimal digits in Java than Python prints, first convert the double to a BigDecimal (this operation is lossless) and then print that BigDecimal number.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • I'm having some trouble finding a java `Decimal` class. Could you possibly be referring to the `BigDecimal` class? I've done some tests with that and haven't had any luck so far. When I convert my `double` to a `BigDecimal` and print format it with `"%.25f" format bigDec` I get a value like `res0: String = 0.1000000000000000000000000`. – bnsmith Dec 09 '15 at 13:59
  • @bnsmith yes, I meant BigDecimal. Beware that the value must be a double before being a BigDecimal in order for the trick to work. If you create a BigDecimal directly from the string `"0.1"` for instance you will get the BigDecimal for 1/10, not for the double nearest to that. – Pascal Cuoq Dec 09 '15 at 17:24
  • @bnsmith The author of this question is complaining that they see the very decimals you want to see: http://stackoverflow.com/questions/12395281/convert-double-to-bigdecimal-and-set-bigdecimal-precision I tried to make a short demo Scala program but ideone.com is uncooperative. – Pascal Cuoq Dec 10 '15 at 15:35