1
$\begingroup$

Multiplying and dividing by the same stuff seems to alter the value. Quite curiously, if the value you start from is large enough (greater than 0.05 in my case) you do not see the problem. Any idea why?

  • MemberQ[{0.01, 0.05}, (0.05*9*2)/9/2] returns True
  • MemberQ[{0.01, 0.05}, (0.01*9*2)/9/2] returns False

I can fix this using chop, but sounds like a stupid way of doing it

  • MemberQ[Chop[{0.01, 0.05} - (0.05*9*2)/9/2], 0] returns True
  • MemberQ[Chop[{0.01, 0.05} - (0.01*9*2)/9/2], 0] returns True

Any ideas for a better way?

$\endgroup$
  • 3
    $\begingroup$ Never ever compare floating point numbers without a tolerance... $\endgroup$ – Henrik Schumacher Oct 16 '17 at 22:15
  • $\begingroup$ Use rational numbers if you want exact comparisons, i.e., MemberQ[Rationalize[{0.01, 0.05}], Rationalize[(0.01*9*2)/9/2]] $\endgroup$ – bill s Oct 16 '17 at 22:26
  • 1
    $\begingroup$ To elaborate on Henrik's comment, == and even === (!) use a tolerance in Mathematica. But functions like MemberQ, Union, etc. do not, at least not for machine precision numbers. I haven't tried with arbitrary precision ones. $\endgroup$ – Szabolcs Oct 16 '17 at 22:31
  • 1
    $\begingroup$ MemberQ uses MatchQ rather than Equal or SameQ. $\endgroup$ – ngenisis Oct 16 '17 at 23:02
7
$\begingroup$

Contrary to MemberQ, the function ContainsAny has an option SameTest which can be adjusted. For your problem, the option value Equal is sufficient:

ContainsAny[{0.01, 0.05}, {(0.05*9*2)/9./2.}, SameTest -> Equal]
ContainsAny[{0.01, 0.05}, {(0.01*9*2)/9./2.}, SameTest -> Equal]

(* True *)
(* True *)

If you want to compare with respect to a certain tolerance, you can specify your own comparison function, e.g., as follows:

tol = 1. 10^-20;
myequal = {x, y} \[Function] Abs[x - y] < tol;
ContainsAny[list, {x}, SameTest -> myequal]
ContainsAny[list, {y}, SameTest -> myequal]

(* False *)
(* False *)

Here an example, where the actual value of the tolerance matters:

tol = 2. 10^-18;
myequal = {x, y} \[Function] Abs[x - y] < tol;
ContainsAny[list, {x}, SameTest -> myequal]
ContainsAny[list, {y}, SameTest -> myequal]

(* True *)
(* False *)
$\endgroup$
2
$\begingroup$

It is all due to MatchQ, which is what MemberQ uses for making its test. With machine floats:

Table[{i, MatchQ[(i*9*2)/9/2, i]}, {i, .01, .1, .01}] // TableForm

machine

But with Mathematica arbitrary precision numbers, even at low precision

 Table[
   {N[i], With[{j = N[i, 2]}, MatchQ[(j*9*2)/9/2, j]]}, 
   {i, Range[10]/100}] // TableForm

arbitrary

we get the expected result and

MemberQ[{0.01`2, 0.05`2}, (0.01`2*9*2)/9/2]

True

works.

$\endgroup$

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.