Domanda

Vorrei fissare un x valore ad una gamma [a, b]:

x = (x < a) ? a : ((x > b) ? b : x);

Questo è abbastanza semplice. Ma non vedo una funzione di "pinza" nella libreria di classi -. Almeno non in System.Math

(Per l'ignaro a "pinza" un valore è quello di assicurarsi che si trova tra alcuni valori massimi e minimi. Se è superiore al valore massimo, allora è sostituito dal massimo, ecc.)

È stato utile?

Soluzione

Si potrebbe scrivere un metodo di estensione:

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: metodi di estensione vanno in classi statiche - dal momento che questo è piuttosto una funzione di basso livello, probabilmente dovrebbe andare in qualche namespace principale nel progetto. È quindi possibile utilizzare il metodo in qualsiasi file di codice che contiene una direttiva using per lo spazio dei nomi per es.

using Core.ExtensionMethods

int i = 4.Clamp(1, 3);

.NET Nucleo 2.0

A partire da .NET 2.0 Nucleo System.Math ora ha una Clamp metodo che può essere utilizzato al posto:

using System;

int i = Math.Clamp(4, 1, 3);

Altri suggerimenti

Prova:

public static int Clamp(int value, int min, int max)  
{  
    return (value < min) ? min : (value > max) ? max : value;  
}

Basta usare Math.Min e Math.Max:

x = Math.Min(Math.Max(x, a), b);

non è uno, ma non è troppo difficile fare uno. Ho trovato uno qui: morsetto

Si tratta di:

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;
    }

E può essere usato come:

int i = Clamp(12, 10, 0); -> i == 10
double d = Clamp(4.5, 10.0, 0.0); -> d == 4.5

Non è uno nel namespace System.Math

http://msdn.microsoft.com/en-us/ biblioteca / system.math_members.aspx

C'è una classe MathHelper dove è disponibile per lo studio XNA gioco se che sembra essere quello che state facendo:

http://msdn.microsoft.com /en-us/library/bb197892(v=XNAGameStudio.31).aspx

Utilizzando le risposte precedenti, ho condensato giù al di sotto del codice per le mie esigenze. Questo permetterà anche di bloccarlo su un numero solo per la sua minima o massima.

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;
    }
}

Il sotto supporti codice specificano limiti in qualsiasi ordine (cioè bound1 <= bound2, o bound2 <= bound1). Ho trovato questo utile per i valori calcolati dalle equazioni lineari (y=mx+b) in cui la pendenza della linea può essere crescente o decrescente serraggio.

Lo so: il codice è costituito da cinque super-brutto operatori espressione condizionale . La cosa è, funziona , ed i test sotto lo dimostrano. Sentitevi liberi di aggiungere parentesi rigorosamente inutili se lo desiderano.

Si può facilmente creare altri sovraccarichi per altri tipi numerici e fondamentalmente copia / incolla il test.

Attenzione: Confrontando i numeri in virgola mobile non è semplice. Questo codice non implementa confronti double robusto. Utilizzare una libreria di confronto in virgola mobile per sostituire gli usi di operatori di confronto.

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 / test FluentAssertions:

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);
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top