5
$\begingroup$

Please consider the following:

zeros={0.,0};   
data={1, 0., 0}; 
DeleteCases[data, #]&/@zeros
Head/@zeros
(*{Real, Integer}*)
(*{{1, 0}, {1, 0.}}*)

For my understanding all integers (e.g. 0, 2) are element of the real numbers (e.g. 0.00000, 2.00000). So why would Mathematica not delete all zeros form data.

I know from here that one can solve the DeleteCases-problem via DeleteCases[Rationalize@data,0] but this is not the point here.

EDIT

The following test may explain my problem slightly better:

sets={Integers,Reals,Complexes};
test=Table[Element[j, i], {i, sets}, {j, zeros}];
(*{{False, True}, {True, True}, {True, True}}*)

test returns as expected that 0 is element of Integers, Reals and Complexes for which reason I would expect for DeleteCases[data, #]&/@zeros the following result:

{{1}, {1, 0.}}

For the latter 0. can not be deleted from data because I called delete all 0-Integers whereas in the first case all zeros can be deleted as I called delete all 0-Reals.

Note: Instead of 0 and 0. we could use also 2 and 2.. The value does not matter.

$\endgroup$
8
  • $\begingroup$ Are you trying to do DeleteCases[data, 0 | 0.]? As far as I can tell your example works as expected. With /@ you are only deleting one type of zero at a time. $\endgroup$
    – Mr.Wizard
    Commented Oct 22, 2012 at 18:28
  • 1
    $\begingroup$ I shall reopen this question, but I encourage you to expand and clarify it because as it presently reads it looks like a duplicate. $\endgroup$
    – Mr.Wizard
    Commented Oct 22, 2012 at 20:20
  • 1
    $\begingroup$ Incidentally, try: Table[Element[j, i], {i, sets}, {j, zeros}] $\endgroup$
    – Mr.Wizard
    Commented Oct 22, 2012 at 20:22
  • 1
    $\begingroup$ I agree with Mr.Wizard that this is a duplicate. Please explain why exactly it is not and how the other answers do not answer your question. As for 0==0., you should read up the documentation for Equal and SameQ... it's fully covered between the two. $\endgroup$
    – rm -rf
    Commented Oct 22, 2012 at 20:41
  • 2
    $\begingroup$ Element is a mathematical operation, which is why it (correctly) says that 0 is an element of Integers/Reals/Complexes. However, 0. is a floating point representation of zero and is not an exact integer, hence False. It certainly is an element of Reals, and by extension, an element of Complexes which is a superset of Reals, which is why it returns True. DeleteCases uses pattern matching and relies on the heads (or the FullForm) and does not do a mathematical comparison. This is something you need to get comfortable with in order to use Mathematica effectively. $\endgroup$
    – rm -rf
    Commented Oct 22, 2012 at 21:41

2 Answers 2

5
$\begingroup$

Element (of) is a mathematical operation, which is why it (correctly) says that 0 is an element of Integers, Reals and Complexes. However, $0.$ is a floating point representation of zero and is not an exact integer, hence it returns False for Element[0., Integer]. On the other hand, 0. certainly is an element of Reals, and by extension, an element of Complexes which is a superset of Reals, which is why it returns True for both these cases.

DeleteCases uses pattern matching and relies on the heads (or the FullForm) and does not do a mathematical comparison, which is why DeleteCases[list, 0] will not remove instances of 0. in list. The solution in this case is to either use 0 | 0. as the pattern, or use PossibleZeroQ to test the elements of list:

DeleteCases[data, _?PossibleZeroQ]
(* {1} *)

The difference between mathematical operations and the pattern matching logic is something you need to get comfortable with in order to use Mathematica effectively. Another example of a common mistake is to use pattern matching to perform algebraic manipulations.

$\endgroup$
2
  • $\begingroup$ ...or, one might consider preprocessing the data: DeleteCases[Chop[list], 0] $\endgroup$ Commented Oct 22, 2012 at 22:57
  • $\begingroup$ @J.M. well, $10^{-11}$ is still not $0$, and going the extra length of using the second argument seems long winded :) $\endgroup$
    – rm -rf
    Commented Oct 23, 2012 at 0:14
2
$\begingroup$

DeleteCases uses the pattern matcher which matches against the FullForm of expressions. Just use Alternative:

In[]:= DeleteCases[{1, 0., 0}, 0. | 0]
Out[]= {1}

or a conditional pattern

In[]:= DeleteCases[{1, 0., 0}, _?(# == 0 &)]
Out[]= {1}

or

In[]:= DeleteCases[{1, 0., 0}, x_ /; x==0]
Out[]= {1}

This happens a lot with infinity be careful of the heads: Infinity // FullForm is DirectedInfinity[1]

$\endgroup$
3
  • 1
    $\begingroup$ A bit more on the Infinity part: using Infinity in replacement rules or patterns works just as expected, because both expand out to DirectedInfinity (for example: DirectedInfinity[1] /. Infinity -> 1 and Infinity /. Infinity -> 1). The confusion, however, often occurs when one expects division by zero to occur, but then wants to disregard it and replace it with something arbitrary. In that case, it is not DirectedInfinity that's used, but ComplexInfinity and doing foo /. Infinity -> bar will not work $\endgroup$
    – rm -rf
    Commented Oct 22, 2012 at 20:39
  • $\begingroup$ @rm: to catch all forms of *Infinity, one should then match against the pattern _DirectedInfinity, since ComplexInfinity is the same as DirectedInfinity[]. $\endgroup$ Commented Oct 23, 2012 at 0:23
  • $\begingroup$ @J.M. Yes, that is correct. $\endgroup$
    – rm -rf
    Commented Oct 23, 2012 at 0:36

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.