Scala Programming Language
  1. Scala Programming Language
  2. SI-3791

scala.Double.Epsilon is set to wrong value

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Misc Library
    • Labels:
      None
    • Environment:

      Double

      Description

      It's description says: "The smallest difference between two values of Double." However, if you look up its value it's set to java.lang.Double.MIN_VALUE.

      The smallest difference between two Doubles is a lot bigger then the smallest value that can be stored in a Double.

      Here's an exempt from "float.h":

      #define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */

      #define DBL_MIN 2.2250738585072014e-308 /* min positive value */

        Activity

        Hide
        Simon Ochsenreither added a comment -

        I made the changes, pull request here: https://github.com/scala/scala/pull/7

        Show
        Simon Ochsenreither added a comment - I made the changes, pull request here: https://github.com/scala/scala/pull/7
        Hide
        Paul Phillips added a comment -

        (In r24461) Addresses the issues swirling around Double.Epsilon and friends
        which were battled out in more than one venue and then aptly summarized
        by retronym in SI-3791. Thanks to Simon Ochsenreither for submitting
        a patch; I wasn't able to use too much of it because the source
        code for these types is generated, but effort is always
        appreciated. Closes SI-3791, and I'm tired and I'd hate to blow
        this one at this late date: review by rytz.

        Show
        Paul Phillips added a comment - (In r24461) Addresses the issues swirling around Double.Epsilon and friends which were battled out in more than one venue and then aptly summarized by retronym in SI-3791 . Thanks to Simon Ochsenreither for submitting a patch; I wasn't able to use too much of it because the source code for these types is generated, but effort is always appreciated. Closes SI-3791 , and I'm tired and I'd hate to blow this one at this late date: review by rytz.
        Hide
        Dominik Gruntz added a comment -

        Float.Epsilon and Double.Epsilon have been removed in 2.10 (after having been deprecated in 2.9), so it is time to add the correct versions to 2.11.

        Show
        Dominik Gruntz added a comment - Float.Epsilon and Double.Epsilon have been removed in 2.10 (after having been deprecated in 2.9), so it is time to add the correct versions to 2.11.
        Hide
        Dominik Gruntz added a comment -

        Will add the constant Epsilon to the classes Double and Float as follows:

        scala> final val Eps = java.lang.Double.longBitsToDouble(0x3ca0000000000000L)
        Eps: Double = 1.1102230246251565E-16
        
        scala> 1d+Eps == 1d
        res1: Boolean = true
        
        scala> 1d-Eps == 1d
        res2: Boolean = false
        
        scala> final val Eps = java.lang.Float.intBitsToFloat(0x33800000)
        Eps: Float = 5.9604645E-8
        
        scala> 1f+Eps == 1f
        res3: Boolean = true
        
        scala> 1f-Eps == 1f
        res4: Boolean = false
        

        This value gives an upper bound on the relative error due to rounding real numbers to floating point numbers (either Floats or Doubles). For any floating point system with base B and precision (or mantissa length) p this upper bound is defined as B^(-(p-1))/2 (which corresponds to 1/2 ulp = 1/2 unit in the last place).

        • Float (B=2 / p=24): Eps = 2^(-24)
        • Double (B=2 / p=53): Eps = 2^(-53)

        The definition as the smallest value with 1+Eps != 1 or 1-Eps != 1 leads to slightly different values (if not only powers of 2 are considered). The following method computes the smallest value for 1+Eps != 1 for double precision, and you see, the result is the double number which is the neighbor of the above defined value for Epsilon.

        scala> def epsilon = {
             |   def eps(a: Double, b: Double): Double = {
             |     val e = a + (b-a)/2
             |     if(a < e && e < b) {
             |       val f = 1 + e
             |       if(f == 1.0) eps(e, b) else eps(a, e)
             |     } else b
             |   }
             |   eps(0, 1)
             | }
        epsilon: Double
        
        scala> val eps = epsilon
        eps: Double = 1.1102230246251568E-16
        
        scala> 1d+eps==1d
        res1: Boolean = false
        
        scala> f"${java.lang.Double.doubleToLongBits(eps)}%x"
        res2: String = 3ca0000000000001
        
        Show
        Dominik Gruntz added a comment - Will add the constant Epsilon to the classes Double and Float as follows: scala> final val Eps = java.lang.Double.longBitsToDouble(0x3ca0000000000000L) Eps: Double = 1.1102230246251565E-16 scala> 1d+Eps == 1d res1: Boolean = true scala> 1d-Eps == 1d res2: Boolean = false scala> final val Eps = java.lang.Float.intBitsToFloat(0x33800000) Eps: Float = 5.9604645E-8 scala> 1f+Eps == 1f res3: Boolean = true scala> 1f-Eps == 1f res4: Boolean = false This value gives an upper bound on the relative error due to rounding real numbers to floating point numbers (either Floats or Doubles). For any floating point system with base B and precision (or mantissa length) p this upper bound is defined as B^(-(p-1))/2 (which corresponds to 1/2 ulp = 1/2 unit in the last place). Float (B=2 / p=24): Eps = 2^(-24) Double (B=2 / p=53): Eps = 2^(-53) The definition as the smallest value with 1+Eps != 1 or 1-Eps != 1 leads to slightly different values (if not only powers of 2 are considered). The following method computes the smallest value for 1+Eps != 1 for double precision, and you see, the result is the double number which is the neighbor of the above defined value for Epsilon . scala> def epsilon = { | def eps(a: Double, b: Double): Double = { | val e = a + (b-a)/2 | if(a < e && e < b) { | val f = 1 + e | if(f == 1.0) eps(e, b) else eps(a, e) | } else b | } | eps(0, 1) | } epsilon: Double scala> val eps = epsilon eps: Double = 1.1102230246251568E-16 scala> 1d+eps==1d res1: Boolean = false scala> f"${java.lang.Double.doubleToLongBits(eps)}%x" res2: String = 3ca0000000000001
        Hide
        Dominik Gruntz added a comment -
        Show
        Dominik Gruntz added a comment - submitted https://github.com/scala/scala/pull/1076 .

          People

          • Assignee:
            Dominik Gruntz
            Reporter:
            Grard Basler
            TracCC:
            Jason Zaugg, Mark Harrah, Paul Phillips, Seth Tisue, Simon Ochsenreither
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:

              Development