6
$\begingroup$

I'm attempting to add $MachineEpsilon to numbers I am pulling from the domains of 3 interpolating functions. I pulled 3 numbers, and for one of these numbers adding $MachineEpsilon produces a number slightly larger than the first (as expected). For some reason for the second two numbers, adding $MachineEpsilon does nothing - the number stays the same. I noticed that there are more significant digits in the first number than the last two, which I suppose could have something to do with this, but how can I fix this so that adding $MachineEpsilon will create a higher number for the last two numbers? Below is the output that I got by adding $MachineEpsilon to my numbers (lim,lim1,lim2):

 eps=$MachineEpsilon
InputForm[lim]

(*     1.7775896893621104 *)

InputForm[lim + eps]
(* 1.7775896893621106 *)

InputForm[lim1]
(* 4.925661999190314 *)

InputForm[lim1 + eps]
(* 4.925661999190314 *)

InputForm[lim2]
(* 8.10371456559119 *)

InputForm[lim2 + eps]
(* 8.10371456559119 *)

Additionally, this is how I'm pulling the numbers from the interpolating functions (leaving out some unneccessary code for simplicity):

dom = InterpolatingFunctionDomain[First[r /. g1]];
dom1 = InterpolatingFunctionDomain[First[r /. g2]];
dom2 = InterpolatingFunctionDomain[First[r /. g3]];
dom3 = InterpolatingFunctionDomain[First[r /. g4]];
{lim, b} = dom1[[1]];
{lim1, b1} = dom2[[1]];
{lim2, b2} = dom3[[1]];

Thanks for any help! I'm using the pulled numbers and their next closest in plot and have continued to get the pllp error message saying the two numbers are the same.

$\endgroup$
2
  • 5
    $\begingroup$ This is not an issue with $MachineEpsilon; it is an issue with understanding of what epsilon actually represents. It is a scaled unit in the last place such that n and n + n $MachineEpsilon differ. If you add $MachineEpsilon unscaled to values greater than 1, then it is not surprising that they are unchanged by that. $\endgroup$ Commented Jan 9, 2014 at 6:07
  • 2
    $\begingroup$ This is the very essence of what $MachineEpsilon means. See this note, in particular "Variant definitions". Indeed, it would be an issue if you were getting different results. (This is just another way of stating the point already nicely made by @Oleksandr R. Maybe I should leave well enough alone but I wanted to get in a reference of sorts.) $\endgroup$ Commented Jan 9, 2014 at 16:25

1 Answer 1

10
$\begingroup$

This question probably will not receive a "real" answer because it is based on a misconception about what $MachineEpsilon actually is. But, since the question is upvoted, I suppose there is more than one person who is not yet clear on how this is defined. Therefore, here is a comment to try to clarify the definition and tie up the loose ends of the thread.

The reason that adding $MachineEpsilon to numbers larger than 1 does not result in a value different from the original is due to the very definition of $\epsilon$. Namely, it is a scaled unit in the last place, such that $n + n\epsilon$ is the smallest value that is actually greater than $n$:

Log[2, SetPrecision[$MachineEpsilon, Infinity]]
(* -> -52 *)

64-bit IEEE floats have a 53-bit significand, of which 1 bit (the leading 1) is implicit. Thus, we see that $MachinePrecision corresponds to the minimum possible increment of the significand. Another way to see it is the following:

SetPrecision[$MachineEpsilon, Infinity]
(* -> 1/4503599627370496 *)

SetPrecision[1 + $MachineEpsilon, Infinity]
(* -> 4503599627370497/4503599627370496 *)

Floating point arithmetic is based on the idea of scaling the significand (essentially a normalized, fixed-point number) according to the value of the exponent. So, if we want to produce a number $n'$ that differs minimally from some value $n$, we have to scale $\epsilon$ accordingly. In other words, it's not sufficient just to add $MachineEpsilon; you have to multiply by 1 + $MachineEpsilon:

SetPrecision[6.10352, Infinity]
(* -> 3435976299706046/562949953421312 *)

SetPrecision[6.10352 + $MachineEpsilon, Infinity]
(* -> 3435976299706046/562949953421312 *)

SetPrecision[6.10352*(1 + $MachineEpsilon), Infinity]
(* -> 3435976299706047/562949953421312 *)

As pointed out by Daniel Lichtblau, much more information about the value and interpretation of $\epsilon$, as well as a more formal definition, is given on the Wikipedia page.

$\endgroup$
2
  • $\begingroup$ The wiki web page linked to above has an implementation for finding $\epsilon$ using many different languages, is it possible to show an implementation using Mathematica as well? May be then it can be added to the wiki page along with all the other languages? $\endgroup$
    – Nasser
    Commented Jan 10, 2014 at 6:04
  • 1
    $\begingroup$ @Nasser I'm not sure why one would need to find $\epsilon$ when Mathematica has a value ($MachineEpsilon) to tell you what it is. Additionally, Mathematica is already specifically referenced along with its value of $\epsilon$ on the page. So, while we can write a LibraryLink implementation or abuse the VM's handling of Internal`Bags to cast an integer onto a real, there seems no real need or reason to do so. $\endgroup$ Commented Jan 10, 2014 at 6:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.