2013-12-09 4 views
3

나는 바이트를위한 "좋은"2 진수 연산자를 찾기 위해 몇 년 전에 쓴 프로그램을 가지고있다; 바이트 A은 바이트 을 산출하기 위해 바이트 B을 곱한 값으로 남습니다. 연산자는 256x256 바이트 행렬로 정의됩니다. A 클래스 구현의 버전을 아래에서 제거했습니다.==, CompareTo() 및 Equals()가 일치하지 않으면 어떻게됩니까?

Equals()이 참 IFF 배열의 모든 65536 바이트는 동일합니다.

CompareTo()은 연산자의 선형성을 더 선형 (cryto에 좋지 않음)에서 덜 선형 (crypto에 적합)으로 비교합니다.

A.Equals(B) = false 
(A.ComparesTo(B) == 0) = true 

내 질문이 작 : 이것은 좋은 생각이

은 그래서 다음에 모두 해당하는 것으로,이 경우, AB 수 있습니까? 나는 대답이 '아니오'라는 것을 알고 있지만 선형성을 측정하기위한 많은 계산 비용과 내 문제의 좁은 특성을 감안할 때이 설계가 작동합니다. 비슷한 코드 :

if (localMinimumOperator < globalMinimumOperator) 
{ 
    localMinimumOperator = globalMinimumOperator; 
} 

더 읽기 쉽습니다.

내 질문입니다 : ==, CompareTo()== 0Equals() 사이에 어떤 차이가 있습니까? 또는 대체적으로 : 어떤 인터페이스가 어떤 인터페이스를 사용하는지 설명하는 LINQ 확장 메서드 목록이 있습니까 (IEquatable 또는 IComparable)?

Enumerable에 대한이 MSDN 기사보다 더 간결한 내용이 있습니까? 예를 들어

:

IEnumerable<BinaryOperation> distinct = orgList.Distinct(); 

통화 당 Equals(BinaryOperator) : Enumerable.Distinct<TSource> MethodContains()을 수행한다. Sort()OrderBy()CompareTo()을 사용하는 것으로 알고 있습니다.

하지만 무엇에 대해 FindFirst()BinarySearch()?

내 예를 들어 클래스 :

사이에서이 차이의 결과는 무엇
using System; 
using System.Collections.Generic; 
using System.Linq; 


namespace Jww05 
{ 
    public class BinaryOperation : IEquatable<BinaryOperation>, IComparable<BinaryOperation> 
    { 
    #region ClassMembers 

    public List<List<byte>> TruthTable 
    { 
     get 
     { 
     // I don't like giving out the underlying list if I help it 
     var retVal = new List<List<byte>>(OperatorDefintion); 
     return retVal; 
     } 
    } 

    // private data store for TruthTable 
    private List<List<byte>> OperatorDefintion { get; set; } 

    public BinaryOperation() 
    { 
     // initial state is the Identity operator 
     OperatorDefintion = new List<List<byte>>(); 
     for (int i = 0; i < 256; i++) 
     { 
     var curRow = new List<byte>(); 
     for (int j = 0; j < 256; j++) 
     { 
      curRow.Add((byte)(i + j)); 
     } 
     OperatorDefintion.Add(curRow); 
     } 
    } 

    private long MeasureOperatorLinearity() 
    { 
     var diagonalOffsets = new byte[] { 255, 0, 1 }; 

     /* 
     * Code that measures linearity in the original code used the Fast Walsh Hadamard Transform. 
     * That should go here, but it is removed because the FWHT is clutter for the purposes of this question. 
     * 
     * Since I needed a stub for this, I decided to exacerbate the differnece 
     * between CompareTo() == 0 and Equals() 
     * by returning an arbitrary int in lieu of the long CPU intensive Fast Walsh Hadamard Transform. 
     * 
     * If the matrices are identical on an element-by-element basis, then the Faux Linearity will be the the same. 
     * If the faux linearity (sum of terms on the main diagonal and corners) are the same, the underlying matrices could be different on an element-by-element basis. 
     */ 
     long fauxLinearityMeasure = 0; 
     for (var currRow = 0; currRow < OperatorDefintion.Count(); ++currRow) 
     { 
     fauxLinearityMeasure *= 5; 
     fauxLinearityMeasure = diagonalOffsets.Select(diagonalOffset => (byte)(currRow + diagonalOffset)) 
               .Aggregate(fauxLinearityMeasure, (current, offestedIndex) => current + (OperatorDefintion[offestedIndex][currRow])); 
     } 

     return (int)fauxLinearityMeasure; 
    } 

    #endregion ClassMembers 

    #region ComparisonOperations 

    public int CompareTo(BinaryOperation other) 
    { 
     long otherLinearity = other.MeasureOperatorLinearity(); 
     long thisLinearity = MeasureOperatorLinearity(); 
     long linearityDiff = thisLinearity - otherLinearity; 

     // case the differnece of the linarity measures into {-1, 0, 1} 
     return (0 < linearityDiff) ? 1 
      : (0 > linearityDiff) ? -1 
      : 0; 
    } 

    public static bool operator >(BinaryOperation lhs, BinaryOperation rhs) 
    { 
     if (ReferenceEquals(null, lhs) || 
      ReferenceEquals(null, rhs)) 
     { 
     return false; 
     } 
     return (0 < lhs.CompareTo(rhs)); 
    } 

    public static bool operator <(BinaryOperation lhs, BinaryOperation rhs) 
    { 
     if (ReferenceEquals(null, lhs) || 
      ReferenceEquals(null, rhs)) 
     { 
     return false; 
     } 
     return (0 > lhs.CompareTo(rhs)); 
    } 

    public static bool operator <=(BinaryOperation lhs, BinaryOperation rhs) 
    { 
     if (ReferenceEquals(null, lhs) || 
      ReferenceEquals(null, rhs)) 
     { 
     return false; 
     } 

     // equals is cheap 
     if (lhs.Equals(rhs)) 
     { 
     return true; 
     } 

     return (0 > lhs.CompareTo(rhs)); 
    } 

    public static bool operator >=(BinaryOperation lhs, BinaryOperation rhs) 
    { 
     if (ReferenceEquals(null, lhs) || 
      ReferenceEquals(null, rhs)) 
     { 
     return false; 
     } 

     // equals is cheap 
     if (lhs.Equals(rhs)) 
     { 
     return true; 
     } 

     return (0 < lhs.CompareTo(rhs)); 
    } 

    #endregion ComparisonOperations 

    #region EqualityOperators 

    public bool Equals(BinaryOperation other) 
    { 
     if (ReferenceEquals(null, other)) 
     { 
     return false; 
     } 

     var otherTruthTable = other.TruthTable; 
     var thisTruthTable = TruthTable; 
     var isEquals = true; 
     for (int currRow = 0; currRow < thisTruthTable.Count(); ++currRow) 
     { 
     isEquals = isEquals && thisTruthTable[currRow].SequenceEqual(otherTruthTable[currRow]); 
     } 

     return isEquals; 
    } 

    public override bool Equals(object obj) 
    { 
     return Equals(obj as BinaryOperation); 
    } 

    public override int GetHashCode() 
    { 
     return OperatorDefintion.SelectMany(currRow => currRow) 
           .Aggregate(1, (current, currByte) => current * 5 + currByte); 
    } 

    public static bool operator ==(BinaryOperation lhs, BinaryOperation rhs) 
    { 
     if (ReferenceEquals(null, lhs) || 
      ReferenceEquals(null, rhs)) 
     { 
     return false; 
     } 

     return (0 == lhs.CompareTo(rhs)); 
    } 

    public static bool operator !=(BinaryOperation lhs, BinaryOperation rhs) 
    { 
     if (ReferenceEquals(null, lhs) || 
      ReferenceEquals(null, rhs)) 
     { 
     return false; 
     } 

     return (0 != lhs.CompareTo(rhs)); 
    } 

    #endregion EqualityOperators 
    } 
} 
+1

'=='은 정적이고 LINQ는 제네릭을 사용합니다. 그것은 섞이지 않습니다. 기껏해야 그것은 타입을 참조 타입으로 제한 할 수있다. 그렇다면'=='은 참조 평등을 의미 할 것이다. 사실 이것은 일반적인 제네릭에 대한 불만입니다. – harold

+0

관심있는 사람들을 위해 [Linear Cryptanalysis] (http://en.wikipedia.org/wiki/Linear_cryptanalysis)에 내성이있는 연산자를 검색하기 위해 선형성 (affine distance)을 실제로 측정했습니다. –

답변

4

: ==, compareTo와가() == 0과 같음()?

향후 코드를 보는 사람은 정말로 당신을 싫어할 것입니다.

또는 대체 : 어떤 확장 기능이 어떤 인터페이스 (IEquitable 또는 IComparable)를 사용하는지 설명하는 linq 확장 메서드 목록이 있습니까?

나는 대부분 혼자서 찾은 것 같습니다. 어림짐작의 좋은 규칙은 LINQ 기능에 의해 어떤 인터페이스가 사용되는지 전혀 놀랄 일이 없다는 것입니다 (아무 놀람도 당신과는 다른 좋은 디자인의 특징 중 하나입니다). 예를 들어, 요소를 정렬하려면 어떤 특정 순서로 요소가 있어야 하는지를 알아야 할 필요가 있음을 분명히 알면 평등/불평등만으로는 충분하지 않습니다.BinarySearch도 검색하는 동안 "어느 방법으로 가야할지"알 필요가 있습니다. 요소가 현재보다 크면 정렬 된 배열의 위쪽 부분으로 재 저주합니다. 작 으면 정렬이 낮아집니다. 다시 : 분명히 IComparable이 필요합니다. DistinctEqualsGetHashCode이면 충분합니다. - 고유 한 요소 집합을 결정하기 위해 정렬 할 필요가 없습니다. 등등.

+2

미래가 진정으로 당신을 미워할 것입니다. –

+0

이것이 최고의 대답이라고 생각합니다. * 이것을하지 마십시오! * 그러나이 조언을 무시하는 것이 너무 어리석은 경우에는 스스로 해결해야하며 사용하는 모든 작업의 ​​세부 사항을 검토해야합니다. IEquatable과 IComprarable 사이의 차이. –

+0

비교 방법이 적절한 경우 다른 결과를내는 것이 더 바람직합니다. 일치하는 의미를 강요하는 것보다 낫습니다. 객체 X와 Y가 등급을 매길 수있는 기능을 포함하지 않는다면,'X.CompareTo (Y)'는 0을 산출해야합니다. 그러나 객체가 명확하게 같지 않으면'X.Equals (Y)'가 false를 반환해야합니다. 사람들이 참조 평등을 테스트하기를 원하는 클래스는'=='오버라이드를 추가하지 않아야한다. 왜냐하면'=='연산자를 사용하면 연산자가 더 어색해질 것이기 때문이다. – supercat

관련 문제