복붙노트

[SCALA] 어떻게 스칼라에서 피타고라스 정리를 작성합니까?

SCALA

어떻게 스칼라에서 피타고라스 정리를 작성합니까?

이것은 피타고라스의 정리이다. 함수는 SQRT (A * A + B * B)을 반환 길이 그것의 측면 "A"와 "B"에 기초하여 상기 빗변을 산출한다.

문제는 어떻게 그것이 적절한 방법을 구현하는 모든 종류의와 함께 사용할 수있는 것과 같은 방식으로 스칼라 이러한 함수를 정의하는 것입니까?

컨텍스트를 들어, INT, 더블, 지능-이성을 두 번 이성에서 BigInt 또는 당신이 무엇을하고 있는지에 따라에서 BigInt-하여 Rational 유형에 사용할 수학 정리의 전체 도서관, 속도, 정밀도, 정확도와 범위 요구 사항을 상상 .

해결법

  1. ==============================

    1.이것은 단지 스칼라 2.8에서 작동하지만, 작업을 수행합니다 :

    이것은 단지 스칼라 2.8에서 작동하지만, 작업을 수행합니다 :

    scala> def pythagoras[T](a: T, b: T, sqrt: T => T)(implicit n: Numeric[T]) = {
         | import n.mkNumericOps
         | sqrt(a*a + b*b)
         | }
    pythagoras: [T](a: T,b: T,sqrt: (T) => T)(implicit n: Numeric[T])T
    
    scala> def intSqrt(n: Int) = Math.sqrt(n).toInt
    intSqrt: (n: Int)Int
    
    scala> pythagoras(3,4, intSqrt)
    res0: Int = 5
    

    더 일반적으로, 형질 숫자는 이러한 유형의 문제를 해결하는 방법에 관한 기준은 유효하다. 또한 주문을 참조하십시오.

  2. ==============================

    2.가장 확실한 방법 :

    가장 확실한 방법 :

    type Num = {
      def +(a: Num): Num
      def *(a: Num): Num
    }
    
    def pyth[A <: Num](a: A, b: A)(sqrt: A=>A) = sqrt(a * a + b * b)
    
    // usage
    pyth(3, 4)(Math.sqrt)
    

    이것은 여러 가지 이유로 끔찍한입니다. 첫째, 우리는 재귀 형, 민의 문제가있다. 당신은 어떤 정수 값으로 -Xrecursive 옵션을 설정하여이 코드를 컴파일 할 경우에만 (5 숫자에 대한 충분한보다 아마 더) 허용됩니다. 둘째 타입 민은 정의 부재 중 사용량 반사 호출 대응 컴파일되도록하는 수단을 구성한다. 약간을 넣고, pyth이 버전은 종래의 구현보다 느리게 수십만 배의 순서에 실행, 음란 비효율적이다. 구조 유형의 주위에 방법은 없습니다하지만 당신은 정의가 +, *와있는 대한 SQRT 기능이있는 모든 유형의 pyth을 정의하려는 경우.

    마지막으로, 우리는 가장 근본적인 문제에 와서 : 그것은 지나치게 복잡. 왜 이런 식으로 기능을 구현 귀찮게? 실제로, 그것은 이제까지 적용 할 필요가있는 유일한 유형을 말하기에 실제 스칼라 숫자입니다. 따라서, 가장 쉬운 방법은 바로 다음을 수행 할 수있다 :

    def pyth(a: Double, b: Double) = Math.sqrt(a * a + b * b)
    

    모든 문제가 해결! 이 기능은 유형을 두 번, INT, 플로트, 암시 적 변환의 놀라운에 짧은 감사와 같은 홀수 사람의 값에 사용할 수 있습니다. 그것은이 기능은 기술적으로 덜 유연 우리의 구조적 형식의 버전보다 것은 사실이지만, 그것은 훨씬 더 효율적이고 탁월하게 더 읽을 수 있습니다. 우리는 예상치 못한 유형의 정의 +와 *에 대한 Pythagrean 정리를 계산하는 능력을 상실 할 수 있습니다,하지만 난 당신이 그 능력을 놓칠 거라고 생각하지 않습니다.

  3. ==============================

    3.다니엘의 대답에 약간 생각 :

    다니엘의 대답에 약간 생각 :

    나는이 기능은 SQRT 기능을 제공하는 더 적합 할 것이다, 리얼에 숫자를 일반화하는 실험을했습니다. 이 초래 :

    def pythagoras[T](a: T, b: T)(implicit n: Real[T]) = {
       import n.mkNumericOps
       (a*a + b*b).sqrt
    }
    

    이 같은 일반적인 기능에 문자 번호를 사용하여, 까다로운하지만 가능하다.

    def pythagoras[T](a: T, b: T)(sqrt: (T => T))(implicit n: Numeric[T]) = {
       import n.mkNumericOps
       implicit val fromInt = n.fromInt _
    
       //1 * sqrt(a*a + b*b)   Not Possible!
       sqrt(a*a + b*b) * 1    // Possible
    }
    

    SQRT는 두 번째 매개 변수 목록에 전달되는 경우 형식 유추는 더 나은 작동합니다.

    매개 변수 a와 b는 객체로 전달하지만,이 문제를 해결할 수 @specialized 될 것이다. 불행하게도 여전히 수학 연산에 약간의 오버 헤드가 될 것입니다.

    당신은 거의 mkNumericOps의 수입없이 할 수 있습니다. 나는 frustratringly 사랑 받고!

  4. ==============================

    4.java.lang.Math의의 방법이있다 :

    java.lang.Math의의 방법이있다 :

    public static double hypot (double x, double y)
    

    어떤의의 javadoc는 주장한다 :

    src.zip를 찾고 Math.hypot는 기본 방법입니다 StrictMath와 사용 :

    public static native double hypot(double x, double y);
    
  5. from https://stackoverflow.com/questions/485896/how-does-one-write-the-pythagoras-theorem-in-scala by cc-by-sa and MIT license