Double.Epsilon and Single.Epsilon both have invalid values since .NET 1.0.
Details here: https://social.msdn.microsoft.com/Forums/azure/en-US/23c75283-c3c3-41bf-93d9-6b274593c4ed/singleepsilon-isnt
Both properties have a much lower value than they should have. So, let's make these epsilons great again.
I suppose add new constants with valid values:
Single.MachineEpsilon = 1.192092896e–07F;
Double.MachineEpsilon = 2.2204460492503131e–016
cc @tannergooding
I do not believe that this is worth fixing. A short summation is:
Lets start by defining epsilon as the delta between a given representable number and the next representable number. This is used to determine the maximum difference between a given value and the infinitely precise result, regardless of the current rounding direction. This information is useful having because:
To touch on the first point:
0.0 and its next representable value is 4.9406564584124654E-3240.25 and its next representable value is 5.5511151231257827E-170.5 and its next representable value is 1.1102230246251565E-161.0 and its next representable value is 2.2204460492503131E-162.0 and its next representable value is 4.4408920985006262E-164.0 and its next representable value is 8.8817841970012523E-16To touch on the second point, lets look at "0.1 + 0.2 == 0.3", which is 5 floating-point operations (and 4 times the result is rounded):
3FD3333333333334 and 0x3FD3333333333333, respectively (which shows they differ by one bit)Defining a new constant that matches the C/C++ defined epsilon will not fix issues when comparing the delta between results less than 0.5 or greater than 2.0; just as the current epsilon does not work well when comparison results greater than the largest subnormal. Instead, users should look at using things like the newly exposed Math.BitIncrement and Math.BitDecrement (which equate to the IEEE nextUp and nextDown operations and the C/C++ nextToward function). They should also consider checking whether the actual result and the expected result are within an acceptable tolerance of each-other (for which the minimum tolerance is 1-bit and the maximum tolerance is user-defined, depending on a number of factors).
@tannergooding Thanks for the detailed answer. As I can see both Math.BitIncrement and Math.BitDecrement methods let to do the same things as machine epsilon.
With regard to the usage of epsilon.
It can be used to sum a convergent series with the maximum available precision.
Most helpful comment
I do not believe that this is worth fixing. A short summation is:
Lets start by defining
epsilonasthe delta between a given representable number and the next representable number. This is used to determine the maximum difference between a given value and the infinitely precise result, regardless of the current rounding direction. This information is useful having because:To touch on the first point:
0.0and its next representable value is4.9406564584124654E-3240.25and its next representable value is5.5511151231257827E-170.5and its next representable value is1.1102230246251565E-161.0and its next representable value is2.2204460492503131E-162.0and its next representable value is4.4408920985006262E-164.0and its next representable value is8.8817841970012523E-16To touch on the second point, lets look at "0.1 + 0.2 == 0.3", which is 5 floating-point operations (and 4 times the result is rounded):
3FD3333333333334and0x3FD3333333333333, respectively (which shows they differ by one bit)Defining a new constant that matches the
C/C++defined epsilon will not fix issues when comparing the delta between results less than0.5or greater than2.0; just as the current epsilon does not work well when comparison results greater than the largest subnormal. Instead, users should look at using things like the newly exposedMath.BitIncrementandMath.BitDecrement(which equate to the IEEEnextUpandnextDownoperations and the C/C++nextTowardfunction). They should also consider checking whether theactual resultand theexpected resultare within an acceptable tolerance of each-other (for which the minimum tolerance is 1-bit and the maximum tolerance is user-defined, depending on a number of factors).