Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does adding double.epsilon to a value result in the same value, perfectly equal?

Tags:

I have a unit test, testing boundaries:

[TestMethod] [ExpectedException(typeof(ArgumentOutOfRangeException))] public void CreateExtent_InvalidTop_ShouldThrowArgumentOutOfRangeException() {     var invalidTop = 90.0 + Double.Epsilon;     new Extent(invalidTop, 0.0, 0.0, 0.0); }  public static readonly double MAX_LAT = 90.0;  public Extent(double top, double right, double bottom, double left) {     if (top > GeoConstants.MAX_LAT)         throw new ArgumentOutOfRangeException("top"); // not hit } 

I thought I'd just tip the 90.0 over the edge by adding the minimum possible positive double to it, but now the exception is not thrown, any idea why?

When debugging, I see top as coming in as 90, when it should be 90.00000000.... something.

EDIT: I should have thought a bit harder, 90+Double.Epsilon will lose its resolution. Seems the best way to go is do some bit shifting.

SOLUTION:

[TestMethod] [ExpectedException(typeof(ArgumentOutOfRangeException))] public void CreateExtent_InvalidTop_ShouldThrowArgumentOutOfRangeException() {     var invalidTop = Utility.IncrementTiny(90); // 90.000000000000014     // var sameAsEpsilon = Utility.IncrementTiny(0);     new Extent(invalidTop, 0, 0, 0); }  /// <summary> /// Increment a double-precision number by the smallest amount possible /// </summary> /// <param name="number">double-precision number</param> /// <returns>incremented number</returns> public static double IncrementTiny(double number) {     #region SANITY CHECKS     if (Double.IsNaN(number) || Double.IsInfinity(number))         throw new ArgumentOutOfRangeException("number");     #endregion      var bits = BitConverter.DoubleToInt64Bits(number);      // if negative then go opposite way     if (number > 0)         return BitConverter.Int64BitsToDouble(bits + 1);     else if (number < 0)         return BitConverter.Int64BitsToDouble(bits - 1);     else         return Double.Epsilon; }  /// <summary> /// Decrement a double-precision number by the smallest amount possible /// </summary> /// <param name="number">double-precision number</param> /// <returns>decremented number</returns> public static double DecrementTiny(double number) {     #region SANITY CHECKS     if (Double.IsNaN(number) || Double.IsInfinity(number))         throw new ArgumentOutOfRangeException("number");     #endregion      var bits = BitConverter.DoubleToInt64Bits(number);      // if negative then go opposite way     if (number > 0)         return BitConverter.Int64BitsToDouble(bits - 1);     else if (number < 0)         return BitConverter.Int64BitsToDouble(bits + 1);     else         return 0 - Double.Epsilon; } 

This does the job.

like image 584
sprocket12 Avatar asked Dec 16 '14 14:12

sprocket12


People also ask

What is double Epsilon?

This means that Epsilon is the smallest positive Double value greater than zero and represents the smallest possible value and the smallest possible increment for a Double whose exponent is -1022.

What is a good value for epsilon?

The EPSILON property has a value of approximately 2.2204460492503130808472633361816E-16 , or 2-52.

What is the value of float Epsilon?

The value of the Epsilon property is not equivalent to machine epsilon, which represents the upper bound of the relative error due to rounding in floating-point arithmetic. The value of this constant is 1.4e-45.

What is Java Epsilon?

Epsilon is a family of Java-based scripting languages for automating common model-based software engineering tasks, such as code generation, model-to-model transformation and model validation, that work out of the box with EMF (including Xtext and Sirius), UML, Simulink, XML and other types of models.


1 Answers

Per the documentation of Double.Epsilon:

The value of the Epsilon property reflects the smallest positive Double value that is significant in numeric operations or comparisons when the value of the Double instance is zero.

(Emphasis mine.)

Adding it to 90.0 does not produce "the next smallest value after 90.0", this just yields 90.0 again.

like image 181
Jeroen Mostert Avatar answered Sep 18 '22 09:09

Jeroen Mostert