참고 : 나와 동거하십시오. equals를 재정의하는 방법이나 부동 소수점 값을 비교하는 사용자 지정 메서드를 만드는 방법을 묻지 않습니다.스칼라의 부동 소수점 값에 대한 우선 적용 재정의
스칼라는 객체를 값으로 비교할 수 있고 작은 코드로 그렇게 할 수있는 일련의 도구를 제공함으로써 매우 뛰어납니다. 특히 사례 클래스, 튜플 및 전체 컬렉션 비교를 허용합니다.
나는 종종 집중적 인 계산을 수행하고 돌아 가기 위해 간단한 데이터 구조를 생성하는 메소드를 호출했으며, 특정 입력이 주어진 메소드를 호출 한 다음 결과를 하드 코딩 된 값과 비교하는 단위 테스트를 작성할 수 있습니다. . 예를 들어 :
def compute() =
{
// do a lot of computations here to produce the set below...
Set(('a', 1), ('b', 3))
}
val A = compute()
val equal = A == Set(('a', 1), ('b', 3))
// equal = true
이 빈약 예를 들어 내가 부동 소수점 값이 안정적으로 오히려 등호, 다음과 비교되지 않는 점을 감안 여기 등 특정 테스트 라이브러리의 코드, 를 생략하고있어 해당하는 예는 실패 : 내가 원하는 것이 무엇
def compute() =
{
// do a lot of computations here to produce the set below...
Set(('a', 1.0/3.0), ('b', 3.1))
}
val A = compute()
val equal2 = A == Set(('a', 0.33333), ('b', 3.1)) // Use some arbitrary precision here
// equal2 = false
정밀도의 임의의 수준을 사용하는 전화의 모든 부동 소수점 비교를 할 수있는 방법을하는 것입니다. 그러나 Set 나 Double 중 하나를 제어하지는 않습니다.
이중에서 새 클래스로 암시 적 변환을 정의한 다음 해당 클래스를 오버로드하여 true를 반환하려고했습니다. 그런 다음 하드 코드 된 유효성 검사에서 해당 클래스의 인스턴스를 사용할 수 있습니다.
implicit class DoubleAprox(d: Double)
{
override def hashCode = d.hashCode()
override def equals(other : Any) : Boolean = other match {
case that : Double => (d - that).abs < 1e-5
case _ => false
}
}
val equals3 = DoubleAprox(1.0/3.0) == 0.33333 // true
val equals4 = 1.33333 == DoubleAprox(1.0/3.0) // false
그러나 알 수 있듯이 대칭이 깨집니다. 따라서 더 복잡한 데이터 구조 (집합, 튜플, 사례 클래스)를 비교할 때 왼쪽 또는 오른쪽으로 equals()
을 호출하면 선험적으로 정의 할 방법이 없습니다. 모든 구조체를 가로 지르고 그 지점에서 단일 부동 소수점 비교를 수행하는 것처럼 보입니다 ... 그래서 질문은 다음과 같습니다.이 작업을 수행 할 수있는 방법이 있습니까? 보조 노트로
는 : 나는 entire chapter on object equality 여러 블로그에 좋은 읽기를했다,하지만 그들은 단지 상속 문제에 대한 솔루션을 제공하며 기본적으로 관련된 모든 클래스를 소유하고 그들 모두를 변경해야합니다. 그리고 그것 모두는 해결하려고하는 것을 감안할 때 다소 복잡한 것처럼 보입니다.
평등은 메소드가 각 클래스에 추가되고 영구적으로 재정의되어야하기 때문에 Java에서 근본적으로 손상되는 것 중 하나입니다. 필자가 직관적으로 생각하는 것은 컴파일러가 찾을 수있는 비교 방법을 갖는 것입니다. 예를 들어, equals (DoubleAprox, Double)를 제공하면 클래스의 두 객체를 비교할 때마다 사용됩니다.
코드 샘플을 보내 주셔서 감사합니다! 따라서 기본적으로 집합 평등을 위해 ==의 내부 사용을 조정할 방법이 없지만 평등을 재정의하는 전체 라이브러리를 가져올 수 있습니까? 튜플과 배열 같은 일반적인 컬렉션 (이미 Seq와 Map)에 대한 구현이 이미 있다면 의미가 있습니다. 그 도서관을 조사 할거야. 네가 의미하는 바를 이해하고 있니? –
정확하지 않습니다. 아이디어는 스칼라 언어와 핵심 라이브러리 구문 (Tuples, Arrays, Seqs)을 계속 사용하고 spire와 같은 유형 클래스 기반 라이브러리의 기계를 사용하여 사용자 정의 동등 연산자 "==="를 제공하여 사용자가 무엇을 할 수 있는지 네가 원해. 위의 예에서 이들은 표준 스칼라 튜플 및 (자바) 배열이며 일부 사용자 정의 유형이 아닙니다. 그들은 그 자체를 정의하지 않습니다. 사실 뒤에 ===가 추가됩니다. 이 접근법은 scala Seq에도 적용됩니다. 그러나, *** 당신이 평등의 퍼지 개념으로 세트를 사용하는 것에 대해 잊어야한다고 생각합니다. 그건 기본적으로 불가능합니다. *** –
네, 이해합니다. 불가능에 관해서는, 나는 그것이 너무 퍼지기를 원하지 않는다. (단순한 반올림 에러에 실패하지 않기를 바란다.) 대부분의 테스트에서 그것은 아마도 괜찮을 것이고, 불일치를 야기하지 않을 것이지만, 나는 당신의 요지를 얻는다. 감사! –