Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have a function for which 0 is a special case:

f[A___, 0, B___] := 0

But since I am doing numerics, sometimes in the course of things f gets called with 0. instead of 0. Of course I can add the line

f[A___, 0., B___] := 0

But I don't understand why I need to because I don't understand the difference between 0 and 0.. Can anyone illuminate this for me?

(In addition to saving a line of code, or as Jens points out, a couple of characters, I also want to know the difference between them so I don't run into hard-to-debug problems in the future because of something I didn't know about.)

share|improve this question
2  
Mathematica knows the differnece: typing 0.-0 gives the definitive answer: 0. –  bill s Apr 10 '13 at 9:52
    
Related: (5149) –  Mr.Wizard May 8 at 16:53

5 Answers 5

up vote 21 down vote accepted

0. is an approximate real number that is very close to zero, while 0 is exactly zero. They aren't the same object, as 0 === 0. is False, and 0. has a head of Real, while 0 has a head of Integer.

If you want to turn 0. into 0, you can use Chop, although that will replace all approximate numbers within some tolerance (by default 10^(-10)) of zero with 0.

share|improve this answer
2  
+1 - I was writing essentially the same thing while you posted... –  Jens Jun 18 '12 at 20:00
3  
@Jens, @Pillsy, thanks. I arbitrarily choose this as the correct answer. I have chosen to add the line F[A___, a_?(Equal[#, 0] &), B___] to be safe: I do not want to cut off at less than 10^-10. –  Ian Hincks Jun 18 '12 at 20:08
6  
@Ian I recommend a_ /; a==0 in place of a_?(Equal[#, 0] &) -- it is cleaner, and usually a bit faster. –  Mr.Wizard Jun 18 '12 at 23:24
1  
We also have 0.0*I which is a complex number that is approximately zero. Also have 0.0''200 which is a real number known to have absolute value less than 10^-200. I find it inconsistent that Head[Re[0.0 I]] is Real, but Head[Re[1.0''200 I ]] is Integer. –  Ted Ersek Jun 18 '12 at 23:45

How about this pattern instead:

F[A___, 0 | 0., B___] := 0

Now you get zero in both cases.

Regarding the explanation: You obviously know that the 0. comes about when doing numerics, and the reason is that in numerics we're working with approximate real or complex numbers. These are to be distinguished from exact numbers of which 0 is an example.

Both are numbers,

{NumericQ[0], NumericQ[0.]}

{True, True}

but they're different animals as represented by their Head:

{Head[0], Head[0.]}

{Integer, Real}

Therefore, in defining a pattern test, 0 and 0. show up as non-identical.

share|improve this answer

To match all sorts of zero, you can use

F[A___, zero_ /; zero==0, B___] := 0

Another possibility which catches more cases, but also matches some non-zero expressions is to use PossibleZeroQ:

F[A___, _?PossibleZeroQ, B___] := 0
share|improve this answer
    
I favor this method as well. Don't forget the underscore on the LHS though. –  Mr.Wizard Jun 18 '12 at 21:45
    
@Mr.Wizard Are you aware of any issues with 0|0.? (I need to use this right now.) –  Szabolcs Apr 10 '13 at 20:43
    
@Szabolcs only what I illustrated here. Is there some reason you cannot use x_ /; x==0? –  Mr.Wizard Apr 10 '13 at 20:46
    
@Mr.Wizard Performance concerns (it's for a package so it's difficult to assess the performance impact). Your MatchQ[0.000000000000000000, 0 | 0.] example convinced me, thanks! –  Szabolcs Apr 10 '13 at 21:19

Sometimes I define my pattern using a tolerance value to consider zero:

tolerance = 10.^-15;
F[A___, zero_ /; Abs[zero] <= tolerance, B___] := 0;

As said before, using Chop is possible too (and you can use the second argument to set the tolerance):

F[A___, zero_ /; Chop[zero, tolerance]==0, B___] := 0;

And if you want to take more cases (like the cases in PossibleZeroQ), you can wrap your zero by Simplify: Chop[Simplify[zero], tolerance]==0.

share|improve this answer

I think it is worthwhile to include a table of how different methods compare when deciding about possible zero value. My advice is to use PossibleZeroQ, but always make sure to handle/be prepared to all extrema. Let me quote the documentation:

The general problem of determining whether an expression has value zero is undecidable; PossibleZeroQ provides a quick but not always accurate test.

ClearAll[x];
expr = {0, 0., 0.*10^-1, 1.`1 - 1, 0.0000000000000000000, 
        0 + $MachineEpsilon, 0.0001, 0. I, x};

Panel@TableForm[Transpose@{
     FullForm /@ expr,
     Replace[expr, {0 | 0. -> True, _ -> False}, {1}],
     MatchQ[#, 0 | 0.] & /@ expr, (* same as above *)
     (# === 0 \[Or] # === 0.) & /@ expr ,(* 
     not identical to MatchQ above! *)
     # == 0 & /@ expr,
     (NumericQ@# \[And] # == 0) & /@ expr,
     PossibleZeroQ /@ expr (* same as NumericQ && Equal *)
     }, TableHeadings -> {expr, {FullForm, "rule matching", MatchQ, 
      SameQ, Equal, NumericQ && Equal, PossibleZeroQ}}] /. 
 False -> Item[False, Background -> GrayLevel@.95]

enter image description here

Note that returning False for PossibleZeroQ[x] is not correct mathematically (e.g. x could be zero), but sometimes one really only wants to know whether an expression has a numeric value of zero or not (and x doesn't have a value).

Please feel free to add further methods/corrections to this table!

share|improve this answer
    
Maybe consider 1.`1 - 1 as well... –  J. M. Apr 9 '13 at 13:42
    
@J.M. Thanks, added! –  István Zachar Apr 10 '13 at 9:26

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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