How do I find if two variables are approximately equals?

后端 未结 5 1250
夕颜
夕颜 2020-12-03 16:44

I am writing unit tests that verify calculations in a database and there is a lot of rounding and truncating and stuff that mean that sometimes figures are slightly off.

5条回答
  •  醉话见心
    2020-12-03 17:15

    One way to compare floating point numbers is to compare how many floating point representations that separate them. This solution is indifferent to the size of the numbers and thus you don't have to worry about the size of "epsilon" mentioned in other answers.

    A description of the algorithm can be found here (the AlmostEqual2sComplement function in the end) and here is my C# version of it.

    UPDATE: The provided link is outdated. The new version which includes some improvements and bugfixes is here

    public static class DoubleComparerExtensions
    {
        public static bool AlmostEquals(this double left, double right, long representationTolerance)
        {
            long leftAsBits = left.ToBits2Complement();
            long rightAsBits = right.ToBits2Complement();
            long floatingPointRepresentationsDiff = Math.Abs(leftAsBits - rightAsBits);
            return (floatingPointRepresentationsDiff <= representationTolerance);
        }
    
        private static unsafe long ToBits2Complement(this double value)
        {
            double* valueAsDoublePtr = &value;
            long* valueAsLongPtr = (long*)valueAsDoublePtr;
            long valueAsLong = *valueAsLongPtr;
            return valueAsLong < 0
                ? (long)(0x8000000000000000 - (ulong)valueAsLong)
                : valueAsLong;
        }
    }
    

    If you'd like to compare floats, change all double to float, all long to int and 0x8000000000000000 to 0x80000000.

    With the representationTolerance parameter you can specify how big an error is tolerated. A higher value means a larger error is accepted. I normally use the value 10 as default.

提交回复
热议问题