对此没有快速算法。它要求您找到所有平方因数。这至少需要一些分解。
但是您可以大大加快您的方法。首先,您只需要找到直到 n 的立方根的素数,然后使用Fastest way 的建议来测试 n 本身是否是完美平方,以确定整数的平方根是否为整数。
下一个加速,从底层因素向上工作。每次你找到一个质因数时,将 n 除以它,将平方累加。当你减少 n 的大小时,减少你将要达到的极限。这使您可以利用大多数数字可以被一些小数字整除的事实,这会迅速减少您留给因子的数字的大小,并让您更快地切断搜索。
下一个性能改进,开始变得更聪明地知道你用哪些数字来进行试验划分。例如特殊情况 2,则只测试奇数。您刚刚再次将算法的速度提高了一倍。
但是请注意,即使有了所有这些加速,您也只是获得了更有效的蛮力。它仍然是蛮力,并且仍然不会很快。(尽管它通常会比您当前的想法快得多。)
这里有一些伪代码来说明这一点。
integer_sqrt = 1
remainder = 1
# First we special case 2.
while 0 == number % 4:
integer_sqrt *= 2
number /= 4
if 0 == number / 2:
number /= 2
remainder *= 2
# Now we run through the odd numbers up to the cube root.
# Note that beyond the cube root there is no way to factor this into
# prime * prime * product_of_bigger_factors
limit = floor(cube_root(number + 1))
i = 3
while i <= limit:
if 0 == number % i:
while 0 == number % (i*i):
integer_sqrt *= i
number /= i*i
if 0 == number % (i*i):
number /= i
remainder *= i
limit = floor(cube_root(number + 1))
i += 2
# And finally check whether we landed on the square of a prime.
possible_sqrt = floor(sqrt(number + 1))
if number == possible_sqrt * possible_sqrt:
integer_sqrt *= possible_sqrt
else:
remainder *= number
# And the answer is now integer_sqrt * sqrt(remainder)
请注意,各种 +1 是为了避免浮点数不精确的问题。
运行 2700 算法的所有步骤,会发生以下情况:
number = 2700
integer_sqrt = 1
remainder = 1
enter while loop
number is divisible by 4
integer_sqrt *= 2 # now 2
number /= 4 # now 675
number is not divisible by 4
exit while loop
number is not divisible by 2
limit = floor(cube_root(number + 1)) # now 8
i = 3
enter while loop
i < =limit # 3 < 8
enter while loop
number is divisible by i*i # 9 divides 675
integer_sqrt *= 3 # now 6
number /= 9 # now 75
number is not divisible by i*i # 9 does not divide 75
exit while loop
i divides number # 3 divides 75
number /= 3 # now 25
remainder *= 3 # now 3
limit = floor(cube_root(number + 1)) # now 2
i += 2 # now 5
i is not <= limit # 5 > 2
exit while loop
possible_sqrt = floor(sqrt(number + 1)) # 5
number == possible_sqrt * possible_sqrt # 25 = 5 * 5
integer_sqrt *= possible_sqrt # now 30
# and now answer is integer_sqrt * sqrt(remainder) ie 30 * sqrt(3)