New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
scala.Double.Epsilon is set to wrong value #3791
Comments
Imported From: https://issues.scala-lang.org/browse/SI-3791?orig=1 |
@lrytz said: scala> scala.Double.MinValue == -java.lang.Double.MAX_VALUE
res0: Boolean = true
scala> scala.Double.Epsilon == java.lang.Double.MIN_VALUE
res1: Boolean = true where did you find the description "The smallest difference between two values of Double." However, if you look up its value it's set to java.lang.Double.MIN_VALUE"? |
@retronym said: This is the accepted meaning of epsilon. Apache Commons Math defines it as: class MathUtils {
/** Smallest positive number such that 1 - EPSILON is not numerically equal to 1. */
public static final double EPSILON = 0x1.0p-53; Usage: scala> import org.apache.commons.math.util.MathUtils
import org.apache.commons.math.util.MathUtils
scala> (1d - Double.Epsilon) == 1d
res18: Boolean = true
scala> (1d - MathUtils.EPSILON) == 1d
res19: Boolean = false
scala> (1d - MathUtils.EPSILON / 2) == 1d
res20: Boolean = true
scala> MathUtils.EPSILON
res21: Double = 1.1102230246251565E-16 I guess the deviation from the names used in Java stemmed from the confusing name Proposal:
|
@harrah said: |
@retronym said: |
@gbasler said: I am wondering why the c++ libraries define Epsilon as 2.2e-016 and Apache Commons Math uses 1.1e-16. Apparently the difference is in the definition, e.g.: scala> import org.apache.commons.math.util.MathUtils
import org.apache.commons.math.util.MathUtils
scala> (1d - MathUtils.EPSILON) == 1d
res4: Boolean = false
scala> (1d - MathUtils.EPSILON/2) == 1d
res5: Boolean = true
scala> (1d + MathUtils.EPSILON) == 1d
res6: Boolean = true
scala> (1d + 2*MathUtils.EPSILON) == 1d
res7: Boolean = false Apache Commons Math: 1 - EPSILON != 1 |
@TiarkRompf said: |
@retronym said: We could always go with Double.ε ;D |
@retronym said: should be
|
@retronym said:
My 2c:
|
@paulp said: |
@soc said: |
@paulp said: |
@dgruntz said: |
@dgruntz said: 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).
The definition as the smallest value with 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 |
@dgruntz said: |
Samuel Papin (spapin-at-twitter.com) said: scala> val a = java.lang.Double.MIN_VALUE
a: Double = 4.9E-324
scala> val b = 2*java.lang.Double.MIN_VALUE
b: Double = 1.0E-323
scala> a-b
res0: Double = -4.9E-324 And as the pull request on github tells defining a machine epsilon is really opinionated and most programmers would just make their own. Should this issue be closed? |
@Ichoran said: Thanks for calling attention to this. |
@dgruntz said: Regarding the definition: Is it really defined in IEEE754? I just skimmed the spec, but did not find info about the machine epsilon, and on Wikipedia I found the sentence
I remember two definitions:
So I really come to the conclusion that the Scala library should not define such a constant. |
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 */
The text was updated successfully, but these errors were encountered: