2010-08-22 3 views
1

나는 F #을 배우려고합니다.
나는 소수를 배제하는 함수를 작성했습니다.Primefactors in F #

let PrimeFactors x = 
    let rec PrimeFactorsRecursive x div list = 
    if x % div = 0 then PrimeFactorsRecursive (x/div) div list @ [div] 
    elif div > int(System.Math.Sqrt(float(x))) then 
     if x > 1 then list @ [x] 
     else list 
    else PrimeFactorsRecursive x (div + 1) list 
    PrimeFactorsRecursive x 2 [] 

이제는 좋은 F # 기능인지 또는 "C#, f #"으로 작성된 것인지 확실하지 않습니다.

이 코드를 작성하는 데 "더 많은"기능적 방법이 있습니까?

답변

3

코드의 근본적인 문제는 @을 사용하여 두 개의 목록을 연결한다는 것입니다. 두 목록을 연결하면 일정 시간이 아닌 선형 시간이 소모됩니다.

let primeFactors x = 
    let rec fact x div list = 
     if x % div = 0 then 
      fact (x/div) div (div::list) 
     elif div > int(sqrt (float x)) then 
      if x > 1 then x::list 
      else list 
     else 
      fact x (div+1) list 
    fact x 2 [] 

는 또한 let 바인드 값은 일반적 camleStyle 명명 전환을 다음과 같다 아래와 같이

정수 방법 :: 연산자를 사용하여리스트의 선두에 새로운 소수를 추가하는 것이다. 또 다른 "개선"아직 언급되지

+0

는 @'보고'초보자 F 번호 프로그래머의 코드 냄새 것을 동의하는 대신

int(System.Math.Sqrt(float(x))) 

있도록 배관을 사용하는 것입니다. – Brian

+0

감사. (div :: list)는 여전히 내 레퍼토리에서 누락되었습니다. – Nils

0

if 식 중첩을 줄이려면 보호 된 패턴을 사용할 수 있습니다. 그것보다 완벽하게 합리적인 관용구적인 기능 코드처럼 보입니다.

1

(x |> float |> sqrt |> int) 
+0

얼마 지나지 않아서이 글을 쓰는 청결 함을 더하고 있는지 잘 모르겠다. – Nils

+1

F #에서는 파이프가 일반적으로 중첩 된 함수 호출보다 선호됩니다. F # 컴파일러가 엄격한 왼쪽에서 오른쪽 방향으로 형식 유추를 수행하기 때문에 실용적인 이유가 있습니다. 그러나 파이핑을 사용하면 입력의 변형을 일련의 단계로 볼 수있는 스타일의 문제이기도합니다. –