-2

Using XUnit I can set a precision when comparing two decimals or doubles:

decimal a = 2.7512m;
decimal b = 2.7502m;

Assert.Equal(a, b, 2);

But I need to check if two Lists of Decimals are equal:

List<Decimal> listA = new List<Decimal> { 2.7512m, 1.1234m }

List<Decimal> listB = new List<Decimal> { 2.7502m, 1.1252m }

Assert.Equal(listA, listB);

In this case Assert.Equal does not have a precision parameter just an IEqualityComparer.

How can I create an IEqualityComparer to accomplish the same?

Is there another option?

Kit
  • 20,354
  • 4
  • 60
  • 103
Miguel Moura
  • 36,732
  • 85
  • 259
  • 481
  • 1
    Do you mean something like [this](https://stackoverflow.com/questions/3874627/floating-point-comparison-functions-for-c-sharp)? – Andy Apr 05 '21 at 23:12

2 Answers2

0

You can do something like this, using each list's enumerator

var firstEnumerator = listA.GetEnumerator();
var secondEnumerator = listB.GetEnumerator();
while (firstEnumerator.MoveNext() && secondEnumerator.MoveNext())
    Assert.Equal(firstEnumerator.Current, secondEnumerator.Current, 2);

This is the basics. You can wrap that up in a method or do a ForEach() over Enumerable.Zip.

Another option would be to implement IEqualityComparer<List<Decimal>>.

Kit
  • 20,354
  • 4
  • 60
  • 103
  • If one of the two collections has more items than the other, it could return true. Maybe add a count check first? – Silvermind Apr 05 '21 at 23:23
  • @Silvermind for sure. This is a naive implementation, and definitely could use some checks. – Kit Apr 05 '21 at 23:27
0

Try following :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Decimal> listA = new List<Decimal> { 2.7512m, 1.1234m };
            List<Decimal> listB = new List<Decimal> { 2.7502m, 1.1252m };

            CompareDecimal compareDecimal = new CompareDecimal();
            Dictionary<List<decimal>, string> dict = new Dictionary<List<decimal>, string>(compareDecimal);

            dict.Add(listA, "list 1");
            dict.Add(listB, "list 2");

        }
    }
    public class CompareDecimal : IEqualityComparer<List<decimal>>
    {

        public bool Equals(List<decimal> a, List<decimal> b)
        {
            if (a.Count != b.Count) return false;

            for (int i = 0; i < a.Count; i++)
            {
                if ((decimal)Math.Abs(a[i] - b[i]) > 0.01M)
                    return false;
            }
            return true;

        }

        public int GetHashCode(List<decimal> compareDecimal)
        {
            return 1;
        }
    }

}
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • I would change hash code to just return 1. The hash code is used for a first level test of equality. The above hash code equality will fail under following condition 2.699 and 2.700. – jdweng Apr 06 '21 at 05:52