0

Hi I am new to Scala and the following behavior is really weird. Is Scala making mistake even for this simple calculation? Or I am doing something wrong? Thanks,

scala $ Welcome to Scala 2.12.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.

scala> val radius:Double = 10.2
radius: Double = 10.2

scala> radius * 10
res0: Double = 102.0

scala> radius * 100
res1: Double = 1019.9999999999999

scala> radius * 1000
res2: Double = 10200.0
Pan Wu
  • 1
  • 1
    Where's the mistake? – Dima Jan 28 '18 at 03:23
  • Real numbers like 100 are only approximated when represented in floating point. This might help http://fabiensanglard.net/floating_point_visually_explained/ – roby Jan 28 '18 at 03:27

2 Answers2

2

A Double in Scala is a 64-bit IEEE-754 floating point number equivalent to Java's double primitive type, as described in Scala's doc.

By nature of floating point number, a Double doesn't necessarily return the exact value of a number. It boils down to the fact that decimals can't always be precisely represented as binary.

For better precision, you might want to consider using BigDecimal.

Leo C
  • 22,006
  • 3
  • 26
  • 39
0

Real numbers are represented by Float (32-bit) and Double (64-bit). These are binary formats which only approximately represent the complete range of Real numbers. Real numbers include all the Rationals (countable infinite), and the Irrationals (uncountable infinite). Double can at best represent only a small, finite subset of the Rationals.

The IEEE-754 double precision floating point encoding uses 53-bit mantissa (52-bits explicitly stored), an 11-bit exponent, and 1-bit for sign. Read about IEEE Double precision floating point here.

The range of integers which can be exactly represented is +/- 2^53-1, while the exponent represents a range of 10^+/-308.

  • You cannot express an integer x exactly where |x| > 2^53.

  • You cannot express fractions exactly which are not of the form k/2^n, where k, n are integers (and k, n are within above limits). Thus, you cannot represent 1/3, 1/5, 1/7, 1/11, etc.

  • Any rational fraction where the denominator is relatively prime to 2 cannot be exactly represented. Any fraction k/P, where P is the product of primes other than 2, and k is not a multiple of P, cannot be exactly represented by IEEE-754 floating point.

The behavior you are observing is due to 1/5 being approximately represented, and the conversion from internal double/float representation to character representation performs rounding to some precision. All languages which use machine floating point (double/float) exhibit similar behavior, but the routines which convert from float to print may round these approximate numbers differently.

As a consequence of Cantor's proof that the Real numbers are uncountable and the Rational numbers are countable, almost all Real numbers are irrational.

ChuckCottrill
  • 4,360
  • 2
  • 24
  • 42