c# - vector3 - mathf unity 5
¿Dónde puedo encontrar la función "abrazadera" en.NET? (7)
Me gustaría fijar un valor x
a un rango [a, b]
:
x = (x < a) ? a : ((x > b) ? b : x);
Esto es bastante básico. Pero no veo una función "abrazadera" en la biblioteca de clases, al menos no en System.Math
.
(Para los desconocedores "sujetar" un valor es asegurarse de que se encuentra entre algunos valores máximos y mínimos. Si es mayor que el valor máximo, entonces es reemplazado por el máximo, etc.)
No hay uno en el espacio de nombres System.Math
http://msdn.microsoft.com/en-us/library/system.math_members.aspx
Hay una clase MathHelper donde está disponible para el estudio XNA si eso es lo que estás haciendo:
http://msdn.microsoft.com/en-us/library/bb197892(v=XNAGameStudio.31).aspx
No hay uno, pero no es muy difícil hacer uno. Encontré uno aquí: clamp
Es:
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;
}
Y se puede usar como:
int i = Clamp(12, 10, 0); -> i == 10
double d = Clamp(4.5, 10.0, 0.0); -> d == 4.5
Puedes escribir un método de extensión:
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;
}
EDITAR: los métodos de extensión van en clases estáticas, ya que se trata de una función bastante de bajo nivel, probablemente debería ir en algún espacio de nombres central en su proyecto. A continuación, puede utilizar el método en cualquier archivo de código que contenga una directiva de uso para el espacio de nombres, por ejemplo
using Core.ExtensionMethods
int i = 4.Clamp(1, 3);
.NET Core 2.0
Comenzando con .NET Core 2.0 System.Math
ahora tiene un método Clamp
que se puede usar en su lugar:
using System;
int i = Math.Clamp(4, 1, 3);
Simplemente compartiendo la solución de Lee con los problemas y preocupaciones de los comentarios, cuando sea posible:
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;
}
Diferencias
- El nombre del método utiliza el tiempo verbal apropiado (
ed
) para (más) indicar que el valor no está fijado en el lugar, y que, en cambio, se devuelve un nuevo valor (Ver el comentario de @JimBalter ). - Hace una
null check
apropiada en todas las entradas (Ver el comentario de @JeppeStigNielsen ). - Intercambia
min
ymax
simin > max
(Ver el comentario de @JeppeStigNielsen ).
Limitaciones: sin abrazaderas de un solo lado. Si max
es NaN
, siempre devuelve NaN
(ver el comentario de Herman ).
Solo use Math.Min
y Math.Max
:
x = Math.Min(Math.Max(x, a), b);
Tratar:
public static int Clamp(int value, int min, int max)
{
return (value < min) ? min : (value > max) ? max : value;
}
Usando las respuestas anteriores, la resumí en el código siguiente para mis necesidades. Esto también le permitirá fijar un número solo por su mínimo o máximo.
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;
}
}