2011-02-18 3 views
2

죄송 평방 응원 할 때 (근사하지)를,하지만 난 (편집 주시기 바랍니다) 제대로 명시하는 방법을 모른다, 그래서 예를 줄 것이다 :가장 빠른 알고리즘이 불분명 제목

을 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를 사용하고 물론 나는 적절한 구문

+3

의 모든 정수 인수 분해 알고리즘을 할 것입니다,하지만 구현하기가 어렵습니다. 위의 내용이 귀하의 목적에 충분히 빠르지 않다고 생각하는 이유는 무엇입니까? 실용적인 세계에서 가장 빠른!문제가 너무 어렵고 불필요한 경우 가장 좋습니다. – mellamokb

+0

이 알고리즘은 2700처럼 더 흥미로운 경우에는 작동하지 않는 것 같습니다. –

+0

그래, 가장 실용적인 의미가 무엇입니까 – Templar

답변

3

빠른 알고리즘이 없습니다. 모든 사각형 요소를 찾아야합니다. 이렇게하려면 적어도 일부 인수 분해가 필요합니다.

그러나 접근 방법의 속도를 상당히 높일 수 있습니다. 처음에는 n의 입방체 루트까지 소인수를 찾아서 Fastest way to determine if an integer's square root is an integer의 조언을 사용하여 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) 
+0

당신은 말했다 : "그렇다면 n 자체가 완벽한 사각형인지 테스트한다"그래서 (sqrt (D) = floor (sqrt (D)))로 테스트 할 수 없다? 또한 소수를 말하면, 나는 그것을 얻을 수있는 방법, 루프 내에서 하나의 숫자 만 증가시킬 수 있음을 의미합니다. – Templar

+0

@Templar : 플로어 (sqrt (D))의 문제는 부동 소수점의 부정확성으로 인해 floor (sqrt * k))는 k-1이된다. 그러나 n == floor (sqrt (n + 1)) ** 2인지 여부를 테스트 할 수 있으며 수조에 해당하는 숫자에 대해 신뢰할 수 있어야합니다. 소수를 찾는 것에 관해서는 말했듯이 할 수 있습니다. 테스트 2, 테스트 3, 5, 7, 9, 11, ... - 당신은 여분의 일을 할 것이지만 모든 소수를 얻을 것입니다. 소수 만 찾아서 나누기를 원한다면 많은 합병증이 생길 것입니다. 합병증은 수 백만 명이 넘을 때까지 돈을 지불하지 않을 것입니다. – btilly

+0

이해가 안되네, 나 한테 보여 줄 수있어, 제발? – Templar

0
  1. 목록을 참조하십시오 2700 = 2 * 2 * 3 * 3 * 3 * 5 * 5. 이것은 가장 느린 단계이며 sqrt (N) 작업이 필요합니다.
  2. 누적 계산기를 만듭니다 (1로 시작). 이 목록을 스캔하십시오. 모든 쌍의 수에 대해 누산기를 그 중 하나 (하나)로 곱하십시오. 위의 목록을 스캔 한 후 2 * 3 * 5가됩니다.
  3. 누산기가 승수입니다. 나머지는 제곱근 아래에 있습니다.
+0

비관적 인 경우는 그보다 훨씬 비관적이어야합니다. – btilly

+0

@btilly 예? 약수 목록을 찾으려면, 2^N은 N 개의 연산을 필요로하며, 소수는 sqrt (P)가 필요합니다. –

+0

죄송합니다. 의견을 제출할 때 내 페이지를 업데이트하지 않았으며 원래 로그 (n) 견적을 보았습니다. – btilly