我很好奇,如果你们中的任何一个人想出一个更简化的代码来计算布朗数字。截至目前,此代码可以在进行爬网之前执行~650!
。布朗数的计算方法是n! + 1 = m**(2)
其中M
是一个整数
brownNum = 8
import math
def squareNum(n):
x = n // 2
seen = set([x])
while x * x != n:
x = (x + (n // x)) // 2
if x in seen: return False
seen.add(x)
return True
while True:
for i in range(math.factorial(brownNum)+1,math.factorial(brownNum)+2):
if squareNum(i) is True:
print("pass")
print(brownNum)
print(math.factorial(brownNum)+1)
break
else:
print(brownNum)
print(math.factorial(brownNum)+1)
brownNum = brownNum + 1
continue
break
print(input(" "))
答案 0 :(得分:3)
抱歉,我不明白你的代码背后的逻辑。
我不明白为什么每次通过math.factorial(brownNum)
循环使用相同的brownNum
值计算while True
4次。在for
循环中:
for i in range(math.factorial(brownNum)+1,math.factorial(brownNum)+2):
i
仅取值math.factorial(brownNum)+1
无论如何,这是我的Python 3代码,用于强力搜索Brown numbers。它很快找到了只有3对已知对,然后在这台2GHz 32位机器上大约1.8秒内测试1000以下的所有其他数字。在那一点之后你可以看到它放慢速度(它在20秒左右达到2000点)但是它会快乐地突然行进,直到因子太大而你的机器不能容纳。
我将进度信息打印到stderr,以便它可以与Brown_number对输出分开。此外,与stdout不同,stderr在不打印换行符时不需要刷新(至少,它不在Linux上)。
import sys
# Calculate the integer square root of `m` using Newton's method.
# Returns r: r**2 <= m < (r+1)**2
def int_sqrt(m):
if m <= 0:
return 0
n = m << 2
r = n >> (n.bit_length() // 2)
while True:
d = (n // r - r) >> 1
r += d
if -1 <= d <= 1:
break
return r >> 1
# Search for Browns numbers
fac = i = 1
while True:
if i % 100 == 0:
print('\r', i, file=sys.stderr, end='')
fac *= i
n = fac + 1
r = int_sqrt(n)
if r*r == n:
print('\nFound', i, r)
i += 1
答案 1 :(得分:2)
您可能想要:
num_fac = math.factorial(brownNum)
而不是多次调用应该让你跑到机器的硬限制
答案 2 :(得分:1)
我要做的一个优化就是实现一个&#39;包装器&#39; math.factorial周围的函数缓存了之前的阶乘值,因此当你的brownNum增加时,阶乘没有那么多的工作要做。这被称为&#39; memoization&#39;在计算机科学。
编辑:找到了另一个具有相似意图的答案:Python: Is math.factorial memoized?
答案 3 :(得分:1)
您还应该更准确地将平方根初始化为根。
e = int(math.log(n,4))
x = n//2**e
由于4**e <= n <= 4**(e+1)
,平方根将介于x/2
和x
之间,这应该会产生第一次迭代时Heron公式的二次收敛。