Machine Epsilon is not equal to $MachineEpsilon

4

1

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.

Robin Geyer

Posted 2018-08-14T12:56:39.523

Reputation: 43

Question was closed 2020-05-18T02:45:17.153

2

Note that there is Internal`$EqualTolerance which controls the tolerance of Equal. Read more here: https://stackoverflow.com/a/6626748/590388

– Alexey Popkov – 2018-08-14T13:13:47.403

Thanks Alexey, that is exactly the background working logic I looked for. – Robin Geyer – 2018-08-14T14:03:20.137

Answers

2

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.

Lukas Lang

Posted 2018-08-14T12:56:39.523

Reputation: 17 767

Is there a reason for doing it that way? – Robin Geyer – 2018-08-14T14:03:55.627

2

@RobinGeyer So 0.1 + 0.2 == 0.3 will return True. https://stackoverflow.com/a/7545025/6673902

– Chip Hurst – 2018-08-14T14:16:30.237

In[60]:= {0.1 + 0.2 == 0.3, Block[{Internal`$EqualTolerance = 0}, 0.1 + 0.2 == 0.3]}

Out[60]= {True, False} – Chip Hurst – 2018-08-14T14:18:13.110

OK, thanks, that makes sense. However, 7 Guard-Bits seems a little excessive ;-) – Robin Geyer – 2018-08-14T14:37:25.197

3@RobinGeyer depends on your field. I mean the hard alternative would be to fully expose everyone to the full brutality of floating point numbers. – Searke – 2018-08-14T14:59:05.713