# FullSimplify yields different output with exact and decimal input

I'm trying to define a predicate function to identify if the expression is a geometric sequence. This is the function I came up with so far:

ClearAll["Global*"];
geometricSequenceQ[expr_, var_] := Module[{a}, a = (expr /. var -> #) &;
If[FullSimplify[a[1]*(a[2]/a[1])^(var - 1) == a[var],
Assumptions -> var \[Element] Integers && var > 0], True, False]]


But it doesn't seem to work correctly with inputs involving decimals:

In[5]:= geometricSequenceQ[(-1/2)^(5 n), n]
Out[5]= True


(-1/2)^(5 n) is indeed a geometric sequence with the common ratio of (-1/32). However:

In[6]:= geometricSequenceQ[(-0.5)^(5 n), n]
Out[6]= If[(-0.5)^(5 n) == (-0.03125)^n, True, False]


Why is the result different for exact and decimal inputs? Is there other function I can use instead of FullSimplify?

In[12]:= FullSimplify[(-1/2)^(5 n) == (-1/32)^n,
Assumptions -> n > 0 && n \[Element] Integers]
Out[12]= True

In[13]:= FullSimplify[(-0.5)^(5 n) == (-1/32)^n,
Assumptions -> n > 0 && n \[Element] Integers]
Out[13]= (-0.5)^(5 n) == (-(1/32))^n

• as a workaround, wrap the expression inside FullSimplify in Rationalize – george2079 Jun 15 '17 at 15:44
• Yes, it solves the issue with the sequence (-0.5)^(5n). But, for instance, geometricSequenceQ[(E/3.1)^(5 n), n] yields False. – roman465 Jun 15 '17 at 15:57
• Testing for equality of floating point expression is always going to be problematic. You may need to resort to picking a specific value (or perhaps several) for n to test. Even then you might need to use a tolerance on the equality check. – george2079 Jun 15 '17 at 16:04
• Have you thought of using pattern matching? MatchQ[(E 3.3)^(2 n) , Power[a_?NumericQ, Times[n_?IntegerQ, _]]] (* true *). It will take a bit of work to get a pattern to match a few cases. – george2079 Jun 15 '17 at 16:10

The problem is that Simplify/FullSimplify don't have a rule to convert $(-0.1)^{5 n}$ to $(-0.00001)^n$ under the assumption that $n\in \mathbb{Z}$. Mathematica does know when it is valid to do so:

PowerExpand[(a^5)^n, Assumptions->True]


a^(5 n) E^(2 I n [Pi] Floor[1/2 - (5 Arg[a])/(2 [Pi])])

In particular, for $n\in \mathbb{Z}$:

PowerExpand[(a^5)^n, Assumptions->n ∈ Integers]


a^(5 n)

Here is a function that inverts PowerExpand for certain classes of Power objects:

InversePowerExpand[x_] := Replace[
x,
Power[a_Real, n_Integer z_] /; Refine[z ∈ Integers] -> Power[a^n, z]
]


Now, we can add this transformation function to Simplify/FullSimplify:

Assuming[
n ∈ Integers,
Simplify[(-.1)^(5n), TransformationFunctions->{Automatic, InversePowerExpand}]
]


(-0.00001)^n

I use Assuming[assum, Simplify[expr]] instead of the natural Simplify[expr, assum] because the Simplify assumptions don't get transferred to the transformation function InversePowerExpand automatically.

At any rate, for your question:

Assuming[
n ∈ Integers,
Simplify[
(-.5)^(5n) == (-1/32)^n,
TransformationFunctions->{Automatic, InversePowerExpand}
]
]


True

Rationalize real numbers in expr.

ClearAll["Global*"];
geometricSequenceQ[expr_, var_] :=
Module[{a, expr2 = expr /. z_Real :> Rationalize[z, 0]},
a = (expr2 /. var -> #) &;
If[FullSimplify[a[1]*(a[2]/a[1])^(var - 1) == a[var],
Assumptions -> var ∈ Integers && var > 0], True, False]]

geometricSequenceQ[#, n] & /@
{(-1/2)^(5 n), (-0.5)^(5 n), (E/3.1)^(5 n)}

(*  {True, True, True}  *)

• Thank you! This works for all sequences I've tested so far, but I don't think it will leave numeric constants (e.g., Pi, E) as exact: (-E*0.5)^(5 n) /. z_Real :> Rationalize[z, 0] results in (-(148561198/109305221))^(5 n), rather than (-E/2)^(5 n). I guess this may cause wrong result for more complex expressions.. Or am I missing something? – roman465 Jun 15 '17 at 16:48
• @roman465 - I was mistaken. The division in (E/3.1) gets carried out before the rule gets applied. The change in behavior is the increased precision of Rationalize[#, 0]& compared to just Rationalize – Bob Hanlon Jun 15 '17 at 16:58
• So I wrapped the expression with Unevaluated and set the HoldFirst attribute. Now it works just fine! geometricSequenceQ[expr_, var_] := Module[{a, expr2 = (Unevaluated[expr] /. z_Real :> Rationalize[z, 0])}, a = (expr2 /. var -> #) &; If[FullSimplify[a[1]*(a[2]/a[1])^(var - 1) == a[var], Assumptions -> var \[Element] Integers && var > 0], True, False]] SetAttributes[geometricSequenceQ, HoldFirst]` – roman465 Jun 15 '17 at 17:14