16
$\begingroup$

If I evaluate {1, 2, 3, 4}/{5, 6, 0, 8}, obviously I get one warning:

Power::infy: Infinite expression 1/0 encountered. >>

and one entry of ComplexInfinity in the third position of the result. I'd like to eliminate the warnings and get the output with instances of ComplexInfinity deleted.

So far,

DeleteCases[Quiet[{1, 2, 3, 4}/{5, 6, 0, 8}], ComplexInfinity]

is the best way I have to do this. But I'd rather not suppress all messages with Quiet, in case I'm operating on something more complicated than this example.

Rather than cleaning up the mess it causes, is there a clean way to prevent the divide-by-zero operation from happening in the first place?

$\endgroup$
1
  • 8
    $\begingroup$ Maybe DeleteCases[ Quiet[{1, 2, 0, 0}/{5, 6, 0, 8}, {Power::"infy", General::"indet"}], ComplexInfinity | Indeterminate] $\endgroup$ May 10, 2012 at 22:51

4 Answers 4

13
$\begingroup$

You could remove the zero from the denominator, and the corresponding entry from the numerator:

a = {1, 2, 3, 4};
b = {5, 6, 0, 8};

Pick[a, Positive[b]]/Pick[b, Positive[b]]

(*
==> {1/5, 1/3, 1/2}
*)
$\endgroup$
3
  • 1
    $\begingroup$ What about negative numbers? Shouldn't you use something like PossibleZeroQ? $\endgroup$
    – Mr.Wizard
    May 11, 2012 at 3:03
  • $\begingroup$ @Mr.Wizard Sure, if that's a concern. It all depends on what you know about the lists. $\endgroup$ May 11, 2012 at 3:26
  • $\begingroup$ This one is most in the spirit of preventing the error instead of handling it. Thanks. $\endgroup$ May 11, 2012 at 16:33
15
$\begingroup$

You can switch off the 1/0 messages with

Off[Power::infy]

Now 1/0 only returns ComplexInfinity.

If you want to intercept that (your "prevent the divide-by-zero operation from happening in the first place" seems to imply that) you'd have to redefine Power[0,-1]:

Unprotect[Power]
Power[0, -1] = ...;
Protect[Power]

with '...' a definition of your choice. I would strongly advice against modifying a common built-in function like that, though.

$\endgroup$
3
  • 5
    $\begingroup$ Never ever modify built-in commands, the side effects of doing so aren't only often severe, but also very unpredictable. I wouldn't even recommend this as part of an answer. $\endgroup$
    – David
    May 11, 2012 at 1:55
  • $\begingroup$ If you want to redefine built-ins for some particular piece of code, you can use block to avoid undefined behavior and have that definition only apply to your particular code. $\endgroup$
    – jVincent
    May 11, 2012 at 9:35
  • $\begingroup$ @jVincent A particular ingenious version of this can be found in this contribution to the MMA toolbag. But generally, completely Blocking a built-in functions means you have to provide most of its functionality yourself which could be a problem. $\endgroup$ May 11, 2012 at 11:44
9
$\begingroup$

As Daniel commented, you can restrict the scope of Quiet with its second argument:

Quiet[{1, 2, 3, 4}/{5, 6, 0, 8}, Power::infy]

Other messages are still printed:

Quiet[Divide[1, 2, 3], Power::infy]

During evaluation of In[2]:= Divide::argrx: Divide called with 3 arguments; 2 arguments are expected. >>

$\endgroup$
7
$\begingroup$

Since you are asking for "a way to prevent the divide by zero operation from happening in the first place," let me suggest another approach that is just slightly more involved than the obvious answer (i.e., just don't include zeros in b):

Lets' pick two lists that cover various cases with zeros:

a = {1, 2, 3, 4, 0, 0};
b = {5, 6, 0, 8, 1, 0};

Now I'll define a replacement rule:

inertZero = {0|0. -> "0"};

Its purpose is to replace numerical zeros by a string "0". Strings can be used in calculations but don't trigger the errors you want to avoid. This allows you to do the division like so:

c = a/(b /. inertZero)

$\left\{\frac{1}{5},\frac{1}{3},\frac{3}{0},\frac{1}{2},0,0\right\}$

Depending on your needs, this could be the end of the story, showing you visually where the division by zero would have occurred. Note in particular the last entry, where we had a 0/0 division. Here, Mathematica makes a choice for us: instead of returning Indeterminate, it sets the result to zero. If you don't like this resolution, one could change the rule.

But maybe you want more, e.g., rescue the remaining divide-by-zero cases somehow. Not knowing exactly what you want to do with them, I'll just go on by assuming you want them to return Infinity. So obviously we'll need another replacement rule, and let Mathematica draw its own conclusions about where $\infty$ should appear:

Limit[c /. "0" -> ε, ε -> 0]

$\left\{\frac{1}{5},\frac{1}{3},\infty ,\frac{1}{2},0,0\right\}$

$\endgroup$
2
  • $\begingroup$ In the last entry, it seems confusing to say that Mathematica makes a choice for you. Mathematica returns indeterminate on 0/0, however you changed it to 0/"0", which returns 0. So it's your choice, not Mathematica's. $\endgroup$
    – jVincent
    May 11, 2012 at 9:41
  • $\begingroup$ But Mathematica chooses that 0 times an unknown object (here Power["0", -1]) is zero, instead of leaving it unevaluated. $\endgroup$
    – Jens
    May 11, 2012 at 13:33

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.