3
$\begingroup$

I try to wrap my head around machine precision calculations in Mathematica (11.2, Linux). I do not understand the following behavior:

$MachineEpsilon
2.22045*10^-16

$MachinePrecision
15.9546

2^-46 // N
1.42109*10^-14

N[1 + 2^-46, $MachinePrecision] == 1
True

Why does this statement still evaluate to True? It is so far away from $MachineEpsilon that it should evaluate to False?

Furthermore, why does the following yield a result which is exactly equal to a mantissa of just 46bit? I guess its the same answer and the same question as above.

one = 1;
eps = 1;
SetPrecision[one, prec];
SetPrecision[eps, prec];
For[
 SetPrecision[eps = one, MachinePrecision],
 SetPrecision[one + eps, MachinePrecision] != 1,
SetPrecision[eps = eps/2, MachinePrecision]
]
eps

1/70368744177664

What I try to understand is what rules Mathematica applies that lead to such results. My problem is that currently I have the impression that I can't rely on SetPrecision[] etc.

$\endgroup$
  • 2
    $\begingroup$ Note that there is Internal`$EqualTolerance which controls the tolerance of Equal. Read more here: stackoverflow.com/a/6626748/590388 $\endgroup$ – Alexey Popkov Aug 14 '18 at 13:13
  • $\begingroup$ Thanks Alexey, that is exactly the background working logic I looked for. $\endgroup$ – Robin Geyer Aug 14 '18 at 14:03
2
$\begingroup$

This is expected. From the documentation of Equal (==):

Approximate numbers with machine precision or higher are considered equal if they differ in at most their last seven binary digits (roughly their last two decimal digits).

(point 4 under Details)

You can use SameQ (===) (note the . after the 1 to make it a machine precision number):

N[1 + 2^-46, $MachinePrecision] === 1.
(* False *)

N[1 + 2^-52, $MachinePrecision] === 1.
(* True *)

You can also look into Internal`$EqualTolerance as pointed out in the comments. See the linked post for more information.

$\endgroup$
  • $\begingroup$ Is there a reason for doing it that way? $\endgroup$ – Robin Geyer Aug 14 '18 at 14:03
  • 1
    $\begingroup$ @RobinGeyer So 0.1 + 0.2 == 0.3 will return True. stackoverflow.com/a/7545025/6673902 $\endgroup$ – Chip Hurst Aug 14 '18 at 14:16
  • $\begingroup$ In[60]:= {0.1 + 0.2 == 0.3, Block[{Internal`$EqualTolerance = 0}, 0.1 + 0.2 == 0.3]} Out[60]= {True, False} $\endgroup$ – Chip Hurst Aug 14 '18 at 14:18
  • $\begingroup$ OK, thanks, that makes sense. However, 7 Guard-Bits seems a little excessive ;-) $\endgroup$ – Robin Geyer Aug 14 '18 at 14:37
  • 2
    $\begingroup$ @RobinGeyer depends on your field. I mean the hard alternative would be to fully expose everyone to the full brutality of floating point numbers. $\endgroup$ – Searke Aug 14 '18 at 14:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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