很抱歉标题不清楚,但我不知道如何正确说明(随时编辑),所以我举个例子:
sqrt(108)~10.39 ...但我希望它像这个sqrt(108)= 6 * sqrt(3)所以它意味着扩展为两个数字
这就是我的算法
i = floor(sqrt(number)) //just in case, floor returns lowest integer value :)
while (i > 0) //in given example number 108
if (number mod (i*i) == 0)
first = i //in given example first is 6
second = number / (i*i) //in given example second is 3
i = 0
i--
也许你知道更好的算法?
如果重要,我将使用PHP,当然我会使用适当的语法
答案 0 :(得分:3)
没有快速算法。它要求您找到所有平方因子。这至少需要一些因素化。
但是你可以通过相当多的速度加快你的方法。首先,您只需要找到直到n的立方根的素因子,然后使用Fastest way to determine if an integer's square root is an integer的建议测试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)
答案 1 :(得分:2)
这不太可能存在快速算法。请参阅https://mathoverflow.net/questions/16098/complexity-of-testing-integer-square-freeness,尤其是https://mathoverflow.net/questions/16098/complexity-of-testing-integer-square-freeness/16100#16100
答案 2 :(得分:0)