C# 我在哪里可以找到“我在哪里”;夹;NET中的函数?
我想将一个值C# 我在哪里可以找到“我在哪里”;夹;NET中的函数?,c#,clamp,C#,Clamp,我想将一个值x钳制到一个范围[a,b]: x = (x < a) ? a : ((x > b) ? b : x); x=(xb)b:x); 这是很基本的。但是我在类库中没有看到函数“clamp”——至少在System.Math中没有 (对于未意识到“钳制”的人来说,一个值是要确保它位于一些最大值和最小值之间。如果它大于最大值,那么它将被最大值替换,等等)。中没有一个值 有一个MathHelper类,如果您正在做的事情恰好是这样的话,它可以用于:没有,但是创建一个也不太难。我在这里
x
钳制到一个范围[a,b]
:
x = (x < a) ? a : ((x > b) ? b : x);
x=(xb)b:x);
这是很基本的。但是我在类库中没有看到函数“clamp”——至少在System.Math
中没有
(对于未意识到“钳制”的人来说,一个值是要确保它位于一些最大值和最小值之间。如果它大于最大值,那么它将被最大值替换,等等)。中没有一个值
有一个
MathHelper
类,如果您正在做的事情恰好是这样的话,它可以用于:没有,但是创建一个也不太难。我在这里找到了一个:
它是:
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;
}
您可以编写一个扩展方法:
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;
}
.NET核心2.0
从.NET Core 2.0System.Math开始,现在有了一种可以替代的方法:
using System;
int i = Math.Clamp(4, 1, 3);
尝试:
公共静态int钳位(int值、int最小值、int最大值)
{
返回值(值<最小值)?最小值:(值>最大值)?最大值:值;
}
只需使用Math.Min
和Math.Max
:
x = Math.Min(Math.Max(x, a), b);
在可能的情况下,仅分享评论中提出的问题和关注点:
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;
}
公共静态T夹紧(此T值,T最小值,T最大值),其中T:i可比较{
如果(value==null)抛出新的ArgumentNullException(nameof(value),“为null”);
如果(min==null)抛出新的ArgumentNullException(nameof(min),“为null”);
如果(max==null)抛出新的ArgumentNullException(nameof(max),“为null”);
//如果为最小值最大值,则夹紧交换的最小值和最大值
返回值。比较到(最大值)<0?最大值:值。比较到(最小值)>0?最小值:值;
}
差异:
- 方法名称使用适当的动词时态(
ed
)来(进一步)指示值未被钳制到位,而是返回一个新值(请参阅)
- 对所有输入进行适当的
null检查(请参阅)
- 交换
min
和max
如果min>max
(请参阅)
限制:
没有单面夹具。如果max
为NaN
,则始终返回NaN
(请参阅)。根据前面的答案,我将其压缩为以下代码以满足我的需要。这也将允许您仅通过其最小值或最大值钳制数字
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;
}
}
公共静态类IComparableExtensions
{
公共静态T夹紧(此T值,T最小值,T最大值)
其中T:i可比较
{
返回值.CompareTo(最小值)<0?最小值:值.ClampedMaximum(最大值);
}
公共静态T最小值(此T值,T最小值)
其中T:i可比较
{
返回值。比较(最小值)<0?最小值:值;
}
公共静态T最大值(此T值,T最大值)
其中T:i可比较
{
返回值。比较(最大值)>0?最大值:值;
}
}
下面的代码支持以任何顺序指定边界(即bound1如果我想验证[min,max]中参数的范围,我使用以下方便的类:
公共类范围限制,其中T:i可比较
{
公共T Min{get;}
公共T Max{get;}
公共范围限制(最小T,最大T)
{
如果(最小值与(最大值)>0)
抛出新的InvalidOperationException(“无效范围”);
Min=Min;
Max=Max;
}
公共无效验证(T参数)
{
如果(参数比较(最小)<0 | |参数比较(最大)>0)
抛出新的InvalidOperationException(“无效参数”);
}
公共T形夹(T参数)=>参数比较(最小值)<0?最小值:参数比较(最大值)>0?最大值:参数;
}
该类适用于所有可比较的对象。我创建了一个具有特定范围的实例:
RangeLimit范围=新的RangeLimit(0100);
我要么验证一个论点
range.Validate(值);
或将参数钳制到以下范围:
var v=range.Validate(值);
如果您使用的是.NET 5、.NET Core 2.x、3.x...我应该把它放在哪里,并且调用CompareTo比在静态类和.NET framework(不确定mono、compact等)中使用的速度慢,应该为该类型重新编译泛型,并将其与内联进行比较,这样就不会有性能损失。@Frasier除非这是对性能非常敏感的代码,否则这样做不太可能获得任何有意义的性能提升。使其成为泛型可能比节省几微秒更有用。约束到IComparable
的通用版本是不会发生装箱。这应该运行得非常快。请记住,对于double
和float
,CompareTo
方法对应的总顺序是NaN
小于所有其他值,包括NegativeInfinity
。因此它不等同于E.<代码>无论在哪种情况下都需要考虑如何处理<代码>楠<代码>。版本< <代码>代码> <代码>将输出<代码>楠< /代码>,使用<代码>楠<代码> <代码> min <代码>或<代码> max >代码>将有效地构成单面夹具。/code>isNaN
@Danvil:没有“C#类库”。你的意思是“.NET框架”。到了C#7.1还没有呢?@JohnSaunders如果我问如何“限制”,我不相信这是绝对正确的世界上每一个说英语的程序员都会立即知道我的意思。很可能每一个程序员都会知道。在从事这项业务30多年后,我必须找出“钳制”今天的含义。类似于“依赖注入”-“参数化”这是一件很明显的事情,从来没有人写过一本书。@Bob有些词有着历史的、定义明确的含义。Clamp就是其中之一。或者“Limit”会让人产生误解,尤其是“Limit”在数学中已经有了不同的含义
x = Math.Min(Math.Max(x, a), b);
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;
}
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;
}
}
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;
}
}
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);
}
}
System.Math.Clamp