Frage

Ich möchte einen Wert x auf einen Bereich [a, b] einzuspannen:

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

Das ist ganz einfach. Aber ich habe keine Funktion „Klammer“ in der Klassenbibliothek sehen -. Zumindest nicht in System.Math

(Für die nicht bewusst zu „Klemme“ ein Wert, um sicherzustellen, ist, dass es zwischen einigen Maximal- und Minimalwerten liegt. Wenn es größer ist als der Maximalwert, dann wird es durch den max ersetzt, usw.)

War es hilfreich?

Lösung

Sie können eine Erweiterungsmethode schreiben:

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: Erweiterungsmethoden gehen in statischen Klassen - da dies durchaus eine Low-Level-Funktion, ist es wahrscheinlich in einigen Kernnamespace in Ihrem Projekt gehen. Anschließend können Sie das Verfahren in jeder Codedatei verwenden, die eine using-Direktive für den Namespace z enthält.

using Core.ExtensionMethods

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

.NET Core 2.0

Beginnend mit .NET Core 2.0 System.Math hat jetzt ein Clamp Methode, die stattdessen verwendet werden kann:

using System;

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

Andere Tipps

Versuchen Sie:

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

Just Verwendung Math.Min und Math.Max:

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

Es gibt nicht ein, aber es ist nicht allzu schwer zu machen. Ich fand man hier: Klemme

Es ist:

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

Und es kann wie verwendet werden:

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

Es gibt nicht einen im System.Math Namespace

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

Es gibt eine MathHelper Klasse, wo es für XNA Game Studio zur Verfügung, wenn das passiert zu sein, was Sie tun:

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

Just teilen Lees Lösung mit den Kommentaren der Fragen und Bedenken, soweit möglich:

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

Unterschiede:

Einschränkungen: Keine einseitigen Klammern. Wenn max NaN ist, kehrt immer wieder NaN (Siehe Hermans Kommentar ).

die bisherigen Antworten benutzen, ich kondensiert es für meine Bedürfnisse Code unten auf die nach unten. Dies erlaubt es Ihnen auch durch seine min oder max eine Zahl nur zu klemmen.

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

Die folgenden Code unterstützt Grenzen in beliebiger Reihenfolge (d.h. bound1 <= bound2 oder bound2 <= bound1) angibt. Ich habe diese nützlich gefunden für Werte berechnet aus linearen Gleichungen (y=mx+b), wo die Steigung der Linie Klemm kann zu- oder abnimmt.

Ich weiß: Der Code besteht aus fünf Super-hässlich bedingten Ausdruck Operatoren . Die Sache ist, es funktioniert , und die Tests unten beweisen. Fühlen Sie sich frei hinzuzufügen streng unnötige Klammern, wenn Sie dies wünschen.

Sie können ganz einfach andere Überlastungen für andere numerische Typen erstellen und im Grunde Kopieren / Einfügen der Tests.

Achtung: Beim Vergleich Gleitkommazahlen ist nicht einfach. Dieser Code implementiert nicht double Vergleiche robust. Verwenden Sie eine Gleitkomma-Vergleich Bibliothek, um die Verwendung von Vergleichsoperatoren zu ersetzen.

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);
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top