将整数分解为尽可能接近平方的值
Factor an integer to something as close to a square as possible
我有一个函数可以逐字节读取文件并将其转换为浮点数组。它还 returns 所述数组中的元素数。
现在我想将数组重塑为二维数组,形状尽可能接近正方形。
例如,让我们看一下数字 800:
sqrt(800) = 28.427...
现在我可以通过反复试验找出 25*32
将是我正在寻找的解决方案。
如果整数相乘的结果很高,我会减少 sqrt
(四舍五入到最接近的整数),如果结果太低,我会增加它们。
我知道对素数执行此操作的算法,但这对我来说不是必需的。我的问题是即使我实现的蛮力方法有时也会卡住并且永远不会完成(这就是我任意限制迭代的原因):
import math
def factor_int(n):
nsqrt = math.ceil(math.sqrt(n))
factors = [nsqrt, nsqrt]
cd = 0
result = factors[0] * factors[1]
ii = 0
while (result != n or ii > 10000):
if(result > n):
factors[cd] -= 1
else:
factors[cd] += 1
result = factors[0] * factors[1]
print factors, result
cd = 1 - cd
ii += 1
return "resulting factors: {0}".format(factors)
input = 80000
factors = factor_int(input)
在输出上方使用此脚本会卡在循环打印中
[273.0, 292.0] 79716.0
[273.0, 293.0] 79989.0
[274.0, 293.0] 80282.0
[274.0, 292.0] 80008.0
[273.0, 292.0] 79716.0
[273.0, 293.0] 79989.0
[274.0, 293.0] 80282.0
[274.0, 292.0] 80008.0
[273.0, 292.0] 79716.0
[273.0, 293.0] 79989.0
[274.0, 293.0] 80282.0
[274.0, 292.0] 80008.0
[273.0, 292.0] 79716.0
[273.0, 293.0] 79989.0
[274.0, 293.0] 80282.0
[274.0, 292.0] 80008.0
[273.0, 292.0] 79716.0
[273.0, 293.0] 79989.0
[274.0, 293.0] 80282.0
但我想知道是否有更有效的解决方案?当然,我不可能是第一个想做这样的事情的人。
def factor_int(n):
val = math.ceil(math.sqrt(n))
val2 = int(n/val)
while val2 * val != float(n):
val -= 1
val2 = int(n/val)
return val, val2, n
试试:
for x in xrange(10, 20):
print factor_int(x)
有趣的问题,这是您的问题的可能解决方案:
import math
def min_dist(a, b):
dist = []
for Pa in a:
for Pb in b:
d = math.sqrt(
math.pow(Pa[0] - Pb[0], 2) + math.pow(Pa[1] - Pb[1], 2))
dist.append([d, Pa])
return sorted(dist, key=lambda x: x[0])
def get_factors(N):
if N < 1:
return N
N2 = N / 2
NN = math.sqrt(N)
result = []
for a in range(1, N2 + 1):
for b in range(1, N2 + 1):
if N == (a * b):
result.append([a, b])
result = min_dist(result, [[NN, NN]])
if result:
return result[0][1]
else:
return [N, 1]
for i in range(801):
print i, get_factors(i)
这个方法的关键是找到[math.sqrt(N),math.sqrt(N)]的笛卡尔点的最小距离满足N=a*b,a&b整数。
我认为模运算符很适合解决这个问题:
import math
def factint(n):
pos_n = abs(n)
max_candidate = int(math.sqrt(pos_n))
for candidate in xrange(max_candidate, 0, -1):
if pos_n % candidate == 0:
break
return candidate, n / candidate
这是一个直接的方法,可以找到最小、最接近的整数 a
、b
,例如 a * b >= n
和 a <= b
,其中 n
是任意数字:
def factor_int(n):
a = math.floor(math.sqrt(n))
b = math.ceil(n/float(a))
return a, b
试试:
for x in xrange(10, 20):
print factor_int(x)
这是一个基于当前接受的答案的较短代码,它比他们的代码(来自基本的 timeit 测试)更短,运行 所需的时间减少了大约 25%-75%:
from math import sqrt, ceil
def factor_int_2(n):
val = ceil(sqrt(n))
while True:
if not n%val:
val2 = n//val
break
val -= 1
return val, val2
下面是我为测试该方法的效率所做的一个小而混乱的测试:
print("Method 2 is shorter and about {}% quicker".format(100*(1 - timeit(lambda: factor_int_2(12345))/timeit(lambda: factor_int(12345)))))
#returns 'Method 2 is shorter and about 75.03810670186826% quicker'
我有一个函数可以逐字节读取文件并将其转换为浮点数组。它还 returns 所述数组中的元素数。 现在我想将数组重塑为二维数组,形状尽可能接近正方形。
例如,让我们看一下数字 800:
sqrt(800) = 28.427...
现在我可以通过反复试验找出 25*32
将是我正在寻找的解决方案。
如果整数相乘的结果很高,我会减少 sqrt
(四舍五入到最接近的整数),如果结果太低,我会增加它们。
我知道对素数执行此操作的算法,但这对我来说不是必需的。我的问题是即使我实现的蛮力方法有时也会卡住并且永远不会完成(这就是我任意限制迭代的原因):
import math
def factor_int(n):
nsqrt = math.ceil(math.sqrt(n))
factors = [nsqrt, nsqrt]
cd = 0
result = factors[0] * factors[1]
ii = 0
while (result != n or ii > 10000):
if(result > n):
factors[cd] -= 1
else:
factors[cd] += 1
result = factors[0] * factors[1]
print factors, result
cd = 1 - cd
ii += 1
return "resulting factors: {0}".format(factors)
input = 80000
factors = factor_int(input)
在输出上方使用此脚本会卡在循环打印中
[273.0, 292.0] 79716.0
[273.0, 293.0] 79989.0
[274.0, 293.0] 80282.0
[274.0, 292.0] 80008.0
[273.0, 292.0] 79716.0
[273.0, 293.0] 79989.0
[274.0, 293.0] 80282.0
[274.0, 292.0] 80008.0
[273.0, 292.0] 79716.0
[273.0, 293.0] 79989.0
[274.0, 293.0] 80282.0
[274.0, 292.0] 80008.0
[273.0, 292.0] 79716.0
[273.0, 293.0] 79989.0
[274.0, 293.0] 80282.0
[274.0, 292.0] 80008.0
[273.0, 292.0] 79716.0
[273.0, 293.0] 79989.0
[274.0, 293.0] 80282.0
但我想知道是否有更有效的解决方案?当然,我不可能是第一个想做这样的事情的人。
def factor_int(n):
val = math.ceil(math.sqrt(n))
val2 = int(n/val)
while val2 * val != float(n):
val -= 1
val2 = int(n/val)
return val, val2, n
试试:
for x in xrange(10, 20):
print factor_int(x)
有趣的问题,这是您的问题的可能解决方案:
import math
def min_dist(a, b):
dist = []
for Pa in a:
for Pb in b:
d = math.sqrt(
math.pow(Pa[0] - Pb[0], 2) + math.pow(Pa[1] - Pb[1], 2))
dist.append([d, Pa])
return sorted(dist, key=lambda x: x[0])
def get_factors(N):
if N < 1:
return N
N2 = N / 2
NN = math.sqrt(N)
result = []
for a in range(1, N2 + 1):
for b in range(1, N2 + 1):
if N == (a * b):
result.append([a, b])
result = min_dist(result, [[NN, NN]])
if result:
return result[0][1]
else:
return [N, 1]
for i in range(801):
print i, get_factors(i)
这个方法的关键是找到[math.sqrt(N),math.sqrt(N)]的笛卡尔点的最小距离满足N=a*b,a&b整数。
我认为模运算符很适合解决这个问题:
import math
def factint(n):
pos_n = abs(n)
max_candidate = int(math.sqrt(pos_n))
for candidate in xrange(max_candidate, 0, -1):
if pos_n % candidate == 0:
break
return candidate, n / candidate
这是一个直接的方法,可以找到最小、最接近的整数 a
、b
,例如 a * b >= n
和 a <= b
,其中 n
是任意数字:
def factor_int(n):
a = math.floor(math.sqrt(n))
b = math.ceil(n/float(a))
return a, b
试试:
for x in xrange(10, 20):
print factor_int(x)
这是一个基于当前接受的答案的较短代码,它比他们的代码(来自基本的 timeit 测试)更短,运行 所需的时间减少了大约 25%-75%:
from math import sqrt, ceil
def factor_int_2(n):
val = ceil(sqrt(n))
while True:
if not n%val:
val2 = n//val
break
val -= 1
return val, val2
下面是我为测试该方法的效率所做的一个小而混乱的测试:
print("Method 2 is shorter and about {}% quicker".format(100*(1 - timeit(lambda: factor_int_2(12345))/timeit(lambda: factor_int(12345)))))
#returns 'Method 2 is shorter and about 75.03810670186826% quicker'