How to elegantly check if a number is within a range?

后端 未结 27 2239
挽巷
挽巷 2020-11-27 11:17

How can I do this elegantly with C# and .NET 3.5/4?

For example, a number can be between 1 and 100.

I know a simple if would suffice; but the keyword to this

27条回答
  •  天命终不由人
    2020-11-27 12:04

    When checking if a "Number" is in a range you have to be clear in what you mean, and what does two numbers are equal mean? In general you should wrap all floating point numbers in what is called a 'epsilon ball' this is done by picking some small value and saying if two values are this close they are the same thing.

        private double _epsilon = 10E-9;
        /// 
        /// Checks if the distance between two doubles is within an epsilon.
        /// In general this should be used for determining equality between doubles.
        /// 
        /// The orgin of intrest
        ///  The point of intrest
        /// The minimum distance between the points
        /// Returns true iff x  in (x0-epsilon, x0+epsilon)
        public static bool IsInNeghborhood(double x0, double x, double epsilon) => Abs(x0 - x) < epsilon;
    
        public static bool AreEqual(double v0, double v1) => IsInNeghborhood(v0, v1, _epsilon);
    

    With these two helpers in place and assuming that if any number can be cast as a double without the required accuracy. All you will need now is an enum and another method

        public enum BoundType
        {
            Open,
            Closed,
            OpenClosed,
            ClosedOpen
        }
    

    The other method follows:

        public static bool InRange(double value, double upperBound, double lowerBound, BoundType bound = BoundType.Open)
        {
            bool inside = value < upperBound && value > lowerBound;
            switch (bound)
            {
                case BoundType.Open:
                    return inside;
                case BoundType.Closed:
                    return inside || AreEqual(value, upperBound) || AreEqual(value, lowerBound); 
                case BoundType.OpenClosed:
                    return inside || AreEqual(value, upperBound);
                case BoundType.ClosedOpen:
                    return inside || AreEqual(value, lowerBound);
                default:
                    throw new System.NotImplementedException("You forgot to do something");
            }
        }
    

    Now this may be far more than what you wanted, but it keeps you from dealing with rounding all the time and trying to remember if a value has been rounded and to what place. If you need to you can easily extend this to work with any epsilon and to allow your epsilon to change.

提交回复
热议问题