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.

Below is a function intended to test if an expression is a polynomial in which all the coefficients and exponents are integers:

intPolyQ[Optional[_Integer] + 
Plus[Optional[_Integer] x_Symbol^Optional[_Integer] ...], x_] := True;
intPolyQ[___] := False;

It gives unexpected results in some cases. For example,

intPolyQ[#, x] & /@ {x, 2 x, 2 x + 1, 2 x^2 + 3 x, 2 x^2 + 3 x + 1}

gives

{True, True, True, False, True}

which is wrong in the 4th case.

Why does this happen? How do I fix it?

share|improve this question
add comment

2 Answers 2

up vote 4 down vote accepted

Don't quite understand why, but one needs both patterns (Jens' and ywdr1987's) to get True for all the expressions in the example. This can be done using Alternatives or adding an additional definition to cover the pattern in Jens's answer:

ClearAll[intPolyQa];
intPolyQa[HoldPattern[Optional[_Integer] + Plus[Optional[_Integer]
  x_Symbol^Optional[_Integer] ...]],  x_] := True; 
intPolyQa[Optional[_Integer] + Plus[Optional[_Integer] 
  x_Symbol^Optional[_Integer] ...],  x_] := True;
intPolyQa[___] := False;
intPolyQa[#, x] & /@ {x, 2 x, 2 x + 1, 2 x^2 + 3 x, 2 x^2 + 3 x + 1}
(* {True, True, True, True, True}  *)

or

 ClearAll[intPolyQb];
 intPolyQb[Alternatives[HoldPattern[Optional[_Integer] + 
  Plus[Optional[_Integer] x_Symbol^Optional[_Integer] ...]], 
  Optional[_Integer] + Plus[Optional[_Integer]
      x_Symbol^Optional[_Integer] ...]], x_] :=  True;
 intPolyQb[___] := False;
 intPolyQb[#, x] & /@ {x, 2 x, 2 x + 1, 2 x^2 + 3 x, 2 x^2 + 3 x + 1}
 (* {True, True, True, True, True} *)
share|improve this answer
    
You're right (+1). –  Jens Dec 10 '12 at 15:23
add comment

The problem isn't with Optional but with the fact that Plus will evaluate pattern sequences as in _ + _ to get unpleasant results like 2 _. In your pattern, you can prevent this by simply wrapping everything in HoldPattern:

intPolyQ[HoldPattern[
    Optional[_Integer] + 
     Plus[Optional[_Integer] x_Symbol^Optional[_Integer] ...]], x_] :=
   True;
intPolyQ[___] := False;

With this, the function seems to work fine if you also retain your old definitions as @kguler observed:

intPolyQ[#, x] & /@ {x, 2 x, 2 x + 1, 2 x^2 + 3 x, 2 x^2 + 3 x + 1}

(* ==> {True, True, True, True, True} *)

Of course there is also an easier way to test for integer polynomials - let's call the polynomial poly, then you could just do

And @@ IntegerQ /@ CoefficientList[poly]
share|improve this answer
1  
With your definition of intPolyQ, it turns out that intPolyQ[#, x] & /@ {x, 2 x, 2 x + 1, 2 x^2 + 3 x, 2 x^2 + 3 x + 1} returns {False, False, False, True, False} in my computer! What's wrong!? @Jens –  ywdr1987 Dec 10 '12 at 11:24
    
MatchQ[list, {__Integer}] is much faster than And @@ IntegerQ /@ list to check for a list of Integers. @ywdr1987 CoefficientList[#, x] ~MatchQ~ {__Integer} & /@ {x, 2 x, 2 x + 1, 2 x^2 + 3 x, 2 x^2 + 3 x + 1} returns {True, True, True, True, True} here. –  Mr.Wizard Dec 10 '12 at 13:45
    
Oh yes, you need both patterns as @kguler observed. I got True everywhere because I must have not exectuted the Clear so I did have both your and my definitions. –  Jens Dec 10 '12 at 15:21
add comment

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.