python - 如何确定某个数字的分子和幂?
问题描述
8=2^3, 81=3^4.
我怎样才能发现或找出哪个/什么数字可以作为分子和某个数字的幂,例如:
8 是初始/确定的数字,但被拆分为 2 的 3 次方;
2 is the numerator and 3 is the power
是否有任何类型的软件/算法可以为这个问题提供答案,例如 64?
解决方案
您可以通过迭代幂并找到产生整数的最高第 n 个根来做到这一点。
from math import log
def findPower(N):
if N == 0: return (0,1) # support zero
if N < 0: # support negatives
r,p = findPower(-N)
return (-r,p) if p%2 else (N,1)
for power in range(int(log(N,2)),1,-1): # int(log(N,2))=N.bit_length()-1
root = int(N**(1/power))
for r in range(root-1,root+2):
if r**power == N: return (r,power)
return (N,1)
print(findPower(81)) # (3,4)
print(findPower(8)) # (2,3)
print(findPower(371293)) # (13,5)
print(findPower(29**7)) # (29,7)
print(findPower(-232630513987207)) # (-7, 17)
请注意,对于 n = -1、0 或 1,这将返回 (n,1),即使它们都有无限数量的解。它还仅返回偶数幂的正基数。
[编辑]上述功能受到浮点数表示能力的限制。它会阻塞非常大的整数。
这是一种替代方法,它支持 Python 的“无限大小”整数,使用二进制搜索计算第 n 个根,并使用结果指数的素数进行优化。
整数根计算
# integer nth root of number X, Returns None if no exact root
rootMod7 = { p:{d**p%7 for d in range(1,8)} for p in range(1,7) }
def intRoot(X,n):
if n==1 or X==1: return X
odd,bits = X&1, X.bit_length() # odd/even and bit magnitude
if X%7 not in rootMod7[(n-1)%6+1]: return # mod 7 match possible roots
lo,hi = 1<<(bits//n),1<<(bits//n+1) # starting range on log(X,n)
while lo<=hi:
root = (lo+hi)//2 # binary search
if root&1 != odd: root += root < hi # odd/even must match X's
delta = X - root**n
if delta == 0: return root
if delta<0 : hi = root - 2 # adjust range
else: lo = root + 2 # on odd/even boundaries
return None
素数生成器
def quickPrimes(N):
isPrime = [False,True]*(N//2+1)
primes = [2]
for p in range(3,N+1,2):
if not isPrime[p]: continue
primes.append(p)
isPrime[p*p:N+1:p] = (False for _ in range(p*p,N+1,p))
return primes
大量数字的解决方案
# finds base and power where base**power == N
def basePower(N):
base,power = (N,1) if N>=0 else basePower(-N)
if N<1: return (-base,power) if power%2 else (N,1)
maxPower = N.bit_length()
for p in reversed(quickPrimes(maxPower)):
if p>maxPower: continue
root = intRoot(base,p)
while root: # prime factorisation of exponents
maxPower = maxPower//p + 1
base,power = root,power*p
root = intRoot(base,p)
return base,power
此版本可以在合理的时间内处理大量数据。
例如:
basePower(1522756**5553) # (1234, 11106) in 46 seconds, 34,333 digits
basePower(12345**12345) # (12345,12345) in 159 seconds, 50,510 digits
[EDIT2]使用素数分解的更好解决方案:
您可以找到素数并取素数的最大公分母 (gcd)。
例如 216000 的素数因数是 2^6、3^3、5^3,所以幂是 3。对于每个素数,保持 count/3 作为计算底数的幂:2^2 * 3^1 * 5 ^1 = 60。所以 216000 = 60^3
def primeFactors(N): # returns dictionary of {prime:count}
result = dict()
p = 2 # p is a candidate prime factor
while p*p<=N: # prime candidates up to √N (remaining N)
while N%p == 0: # count prime factors
result[p] = result.get(p,0)+1
N //= p # by removing factors, only primes will match
p += 1 + (p&1) # next potential prime
if N>1: result[N] = 1 # anything remaining after √N is a prime
return result
def gcd(a,b=0,*c): # gcd using Euclid's algorithm
if c: return gcd(gcd(a,b),*c) # for multiple values
return a if not b else gcd(b,a%b) # Euclidian division version
def findPower(N):
counts = primeFactors(N) # {prime factor: count}
power = gcd(*counts.values()) # power is gcd of prime counts
base = 1
for f,c in counts.items(): # compute base
base *= f**(c//power) # from remaining prime powers
return base,power
这比之前的大整数解决方案要快得多:
findPower(12345**12345)) # (12345,12345) in 2.8 seconds
推荐阅读
- python - 样本数据脚本查询?
- netlify - 如何在 netlify 上提供 robots.txt 和 sitemap.xml?
- github - 有什么方法可以配置 GitHub 或 ArgoCd 以获取在 JFrog Artifactory 中完成的任何更新的通知?
- node.js - Node.js 关于缓冲区、流、管道、axios、createWriteStream 和 createReadStream 的混淆
- datetime - Elasticsearch NEST 客户端日期时间反序列化
- reactjs - 在 JSX 文件中的空标签 <> 之后需要语法高亮帮助
- python - 为什么每次运行我的函数时都会出错?
- javafx - 如何布局一个用一定比例的可用空间填充的 JavaFX 节点?
- python - 如何在 Python 中删除打印语句中的最后一个空格和换行符?
- c - C 数组指针结构检索信息