Compare commits
12
Commits
patch-1
...
perfect-power
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12abc41bc0 | ||
|
|
b47dd3cbe2 | ||
|
|
65678114e5 | ||
|
|
72767a5ba9 | ||
|
|
074f3f4873 | ||
|
|
710128a204 | ||
|
|
9e2b85bb3d | ||
|
|
2f33d20f00 | ||
|
|
937d189895 | ||
|
|
fa52c95e36 | ||
|
|
492c0cd1b6 | ||
|
|
0b6e74ca6e |
+61
-30
@@ -293,15 +293,16 @@ def perfect_power(n, candidates=None, big=True, factor=True):
|
||||
collected so the largest possible ``e`` is sought. If ``big=False``
|
||||
then the smallest possible ``e`` (thus prime) will be chosen.
|
||||
|
||||
If ``candidates`` for exponents are given, they are assumed to be
|
||||
sorted and the first one that is larger than the computed maximum
|
||||
will signal failure for the routine.
|
||||
|
||||
If ``factor=True`` then simultaneous factorization of n is
|
||||
If ``factor=True`` then simultaneous factorization of ``n`` is
|
||||
attempted since finding a factor indicates the only possible root
|
||||
for n. This is True by default since only a few small factors will
|
||||
for ``n``. This is True by default since only a few small factors will
|
||||
be tested in the course of searching for the perfect power.
|
||||
|
||||
The use of ``candidates`` is primarily for internal use; if provided,
|
||||
False will be returned if ``n`` cannot be written as a power with one
|
||||
of the candidates as an exponent and factoring (beyond testing for
|
||||
a factor of 2) will not be attempted.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
@@ -319,7 +320,24 @@ def perfect_power(n, candidates=None, big=True, factor=True):
|
||||
>>> is2pow = lambda n: bool(n and not n & (n - 1))
|
||||
>>> [(i, is2pow(i)) for i in range(5)]
|
||||
[(0, False), (1, True), (2, True), (3, False), (4, True)]
|
||||
|
||||
It is not necessary to provide ``candidates``. When provided
|
||||
it will be assumed that they are sorted integers and the first
|
||||
one that is larger than the computed maximum exponent possible
|
||||
will signal failure for the routine.
|
||||
|
||||
>>> perfect_power(3**8, [9])
|
||||
False
|
||||
>>> perfect_power(3**8, [2, 4, 8])
|
||||
(3, 8)
|
||||
>>> perfect_power(3**8, [4, 8], big=False)
|
||||
(9, 4)
|
||||
|
||||
See Also
|
||||
========
|
||||
sympy.core.power.integer_nthroot
|
||||
"""
|
||||
from sympy.core.power import integer_nthroot
|
||||
n = as_int(n)
|
||||
if n < 3:
|
||||
if n < 1:
|
||||
@@ -328,8 +346,22 @@ def perfect_power(n, candidates=None, big=True, factor=True):
|
||||
logn = math.log(n, 2)
|
||||
max_possible = int(logn) + 2 # only check values less than this
|
||||
not_square = n % 10 in [2, 3, 7, 8] # squares cannot end in 2, 3, 7, 8
|
||||
min_possible = 2 + not_square
|
||||
if not candidates:
|
||||
candidates = primerange(2 + not_square, max_possible)
|
||||
candidates = primerange(min_possible, max_possible)
|
||||
else:
|
||||
candidates = [i for i in candidates if min_possible <= i < max_possible]
|
||||
if n%2 == 0:
|
||||
e = trailing(n)
|
||||
candidates = [i for i in candidates if e%i == 0]
|
||||
if big:
|
||||
candidates = reversed(candidates)
|
||||
for e in candidates:
|
||||
r, ok = integer_nthroot(n, e)
|
||||
if ok:
|
||||
return (r, e)
|
||||
return False
|
||||
|
||||
|
||||
afactor = 2 + n % 2
|
||||
for e in candidates:
|
||||
@@ -350,30 +382,29 @@ def perfect_power(n, candidates=None, big=True, factor=True):
|
||||
# if it's a trivial power we are done
|
||||
if e == 1:
|
||||
return False
|
||||
|
||||
# maybe the bth root of n is exact
|
||||
r, exact = integer_nthroot(n, e)
|
||||
if not exact:
|
||||
# then remove this factor and check to see if
|
||||
# any of e's factors are a common exponent; if
|
||||
# not then it's not a perfect power
|
||||
n //= afactor**e
|
||||
m = perfect_power(n, candidates=primefactors(e), big=big)
|
||||
if m is False:
|
||||
return False
|
||||
else:
|
||||
r, m = m
|
||||
# adjust the two exponents so the bases can
|
||||
# be combined
|
||||
g = igcd(m, e)
|
||||
if g == 1:
|
||||
return False
|
||||
m //= g
|
||||
e //= g
|
||||
r, e = r**m*afactor**e, g
|
||||
if big:
|
||||
# see if other factors have the same
|
||||
# multiplicity
|
||||
a = afactor**e
|
||||
r, ok = integer_nthroot(n//a, e)
|
||||
if ok:
|
||||
return r*a, e
|
||||
# Look for a smaller exponent:
|
||||
# remove this factor and check to see if
|
||||
# any of e's factors are a common exponent; if
|
||||
# not then it's not a perfect power
|
||||
n //= afactor**e
|
||||
# if we want the biggest exponent then we need
|
||||
# to get the smallest exponent in this call
|
||||
rm = perfect_power(n, candidates=primefactors(e), big=not big)
|
||||
if not rm:
|
||||
return False
|
||||
r, m = rm
|
||||
e //= m
|
||||
r = afactor**m*integer_nthroot(n, e)[0]
|
||||
if not big:
|
||||
e0 = primefactors(e)
|
||||
if len(e0) > 1 or e0[0] != e:
|
||||
if e0[0] != e:
|
||||
e0 = e0[0]
|
||||
r, e = r**(e//e0), e0
|
||||
return r, e
|
||||
@@ -392,7 +423,7 @@ def perfect_power(n, candidates=None, big=True, factor=True):
|
||||
if exact:
|
||||
if big:
|
||||
m = perfect_power(r, big=big, factor=factor)
|
||||
if m is not False:
|
||||
if m:
|
||||
r, e = m[0], e*m[1]
|
||||
return int(r), e
|
||||
|
||||
|
||||
Reference in New Issue
Block a user