Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 求平方根时获得精确答案(非近似值)的最快算法_Algorithm_Math_Square Root - Fatal编程技术网

Algorithm 求平方根时获得精确答案(非近似值)的最快算法

Algorithm 求平方根时获得精确答案(非近似值)的最快算法,algorithm,math,square-root,Algorithm,Math,Square Root,很抱歉,标题不清楚,但我不知道如何正确陈述,请随意编辑,因此我将举个例子: sqrt108~10.39。。。但我希望它像这样,sqrt108=6*sqrt3,所以它意味着扩展成两个数字 这就是我的算法 i = floor(sqrt(number)) //just in case, floor returns lowest integer value :) while (i > 0) //in given

很抱歉,标题不清楚,但我不知道如何正确陈述,请随意编辑,因此我将举个例子:

sqrt108~10.39。。。但我希望它像这样,sqrt108=6*sqrt3,所以它意味着扩展成两个数字

这就是我的算法

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,当然我会使用适当的语法,这不太可能有一个快速算法。特地看

按递增顺序列出所有素因子,例如2700=2*2*3*3*3*5*5。这是最慢的步骤,需要sqrtN操作。 创建一个从1开始的累加器。扫描此列表。对于每对数字,将累加器乘以其中一个。因此,在扫描上面的列表后,得到2*3*5。 累加器是你的乘数。其余部分仍在平方根下。
这方面没有快速算法。它要求你找到所有的平方因子。这至少需要一些分解

但你可以加快你的方法相当多。首先,您只需要找到n的立方根以下的素因子,然后使用来自的建议测试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)

任何整数分解算法都可以,但它们很难实现。是什么让你认为上述操作不够快?在现实世界中,速度最快!=如果这太难了,而且对手头的问题来说没有必要,那就最好了。这个算法似乎不适用于更有趣的情况,比如2700。是的,我的意思是practical@KonradGarus我试过了,它与2700一起工作,它不是返回25*sqrt108吗?你的悲观案例应该比这个悲观得多。@B举个例子吧?为了找到除数列表,2^N需要N个运算,素数需要sqrtP。对不起,我在发表评论时没有更新我的页面,仍然看到了你最初的logn估计。你说:然后测试N本身是否是一个完美的平方,所以我不能用sqrt D=floorsqrt D来测试它吗?同样说到素数,我如何得到它们,我的意思是在循环中,我只能增加1number@Templar:floorsqrtD的问题是浮点不精确可能导致floorsqrtk*k为k-1。但是你可以测试n==floorsqrtn+1**2,这对于数万亿的数字来说应该是可靠的。至于寻找素数,照我说的做。测试2,然后测试3,5,7,9,11,…-你会做额外的工作,但你会得到所有的素数。如果你只想找到素数并除以它们,那将是一个非常复杂的过程,在你超过几百万之前,这很可能不会有回报。我用伪代码更新了它,并跟踪了这个算法是如何将sqrt2700分解成30*sqrt3的。