Where can I find the "clamp" function in .NET?
I would like to bind the value of x to the range [a, b] :
x = (x < a) ? a : ((x > b) ? b : x); It is pretty simple. But I do not see the clip function in the class library - at least not in System.Math .
(In order not to know to “clamp” the value, you need to make sure that it lies between some maximum and minimum values. If it is greater than the maximum value, then it is replaced by max, etc.)
You can write an extension method:
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T> { if (val.CompareTo(min) < 0) return min; else if(val.CompareTo(max) > 0) return max; else return val; } EDIT: extension methods go in static classes - since this is a pretty low-level function, it probably should go into some main namespace in your project. Then you can use the method in any code file that contains the using directive for the namespace, for example
using Core.ExtensionMethods int i = 4.Clamp(1, 3); .NET Core 2.0
Starting with .NET Core 2.0 System.Math now has a Clamp method that can be used instead:
using System; int i = Math.Clamp(4, 1, 3); Try:
public static int Clamp(int value, int min, int max) { return (value < min) ? min : (value > max) ? max : value; } Just use Math.Min and Math.Max :
x = Math.Min(Math.Max(x, a), b); There is none, but it is not so difficult to do. I found one here: clamp
It:
public static T Clamp<T>(T value, T max, T min) where T : System.IComparable<T> { T result = value; if (value.CompareTo(max) > 0) result = max; if (value.CompareTo(min) < 0) result = min; return result; } And it can be used as:
int i = Clamp(12, 10, 0); -> i == 10 double d = Clamp(4.5, 10.0, 0.0); -> d == 4.5 There are no names in the System.Math namespace
http://msdn.microsoft.com/en-us/library/system.math_members.aspx
There is a MathHelper class where it is available for the XNA game studio, if that’s how you do it:
http://msdn.microsoft.com/en-us/library/bb197892(v=XNAGameStudio.31).aspx
Just share Lee's solution with questions and comment problems where possible:
public static T Clamped<T>(this T value, T min, T max) where T : IComparable<T> { if (value == null) throw new ArgumentNullException(nameof(value), "is null."); if (min == null) throw new ArgumentNullException(nameof(min), "is null."); if (max == null) throw new ArgumentNullException(nameof(max), "is null."); //If min <= max, clamp if (min.CompareTo(max) <= 0) return value.CompareTo(min) < 0 ? min : value.CompareTo(max) > 0 ? max : value; //If min > max, clamp on swapped min and max return value.CompareTo(max) < 0 ? max : value.CompareTo(min) > 0 ? min : value; } Differences:
- The method name uses the appropriate tense of the verb (
ed) to (further) indicate that the value is not clamped in place, and instead the new value is returned (see Comment @JimBalter ). - Corresponds to
null checkon all inputs (see @JeppeStigNielsen comment ). - Swaps
minandmaxifmin > max(see @JeppeStigNielsen comment ).
Limitations: No one-way clamps. If max is NaN , always returns NaN (see Hermann's comment ).
Using the previous answers, I condensed it to the bottom code for my needs. It will also allow you to clamp a number only with your minimum or max.
public static class IComparableExtensions { public static T Clamped<T>(this T value, T min, T max) where T : IComparable<T> { return value.CompareTo(min) < 0 ? min : value.ClampedMaximum(max); } public static T ClampedMinimum<T>(this T value, T min) where T : IComparable<T> { return value.CompareTo(min) < 0 ? min : value; } public static T ClampedMaximum<T>(this T value, T max) where T : IComparable<T> { return value.CompareTo(max) > 0 ? max : value; } } The code below supports bound1 <= bound2 in any order (i.e. bound1 <= bound2 or bound2 <= bound1 ). I found this useful for clamp values calculated using linear equations ( y=mx+b ), where the slope of the line can increase or decrease.
I know: the code consists of five supernatural conditional expression operators . The fact is that this works , and the tests below prove it. Feel free to add strictly unnecessary brackets if you want.
You can easily create other overloads for other numeric types and basically copy / paste tests.
Warning: comparing floating point numbers is not easy. This code does not implement double comparisons reliably. Use the floating point comparison library to replace the use of comparison operators.
public static class MathExtensions { public static double Clamp(this double value, double bound1, double bound2) { return bound1 <= bound2 ? value <= bound1 ? bound1 : value >= bound2 ? bound2 : value : value <= bound2 ? bound2 : value >= bound1 ? bound1 : value; } } XUnit / FluentAssertions Tests:
public class MathExtensionsTests { [Theory] [InlineData(0, 0, 0, 0)] [InlineData(0, 0, 2, 0)] [InlineData(-1, 0, 2, 0)] [InlineData(1, 0, 2, 1)] [InlineData(2, 0, 2, 2)] [InlineData(3, 0, 2, 2)] [InlineData(0, 2, 0, 0)] [InlineData(-1, 2, 0, 0)] [InlineData(1, 2, 0, 1)] [InlineData(2, 2, 0, 2)] [InlineData(3, 2, 0, 2)] public void MustClamp(double value, double bound1, double bound2, double expectedValue) { value.Clamp(bound1, bound2).Should().Be(expectedValue); } }