Ich möchte einen Wert x
an einen Bereich klemmen [a, b]
:
x = (x < a) ? a : ((x > b) ? b : x);
Das ist ziemlich einfach. Aber ich sehe keine Funktion "clamp" in der Klassenbibliothek - zumindest nicht in System.Math
.
(Wenn Sie nicht wissen, dass ein Wert "geklemmt" werden soll, müssen Sie sicherstellen, dass er zwischen einigen Maximal- und Minimalwerten liegt. Wenn er größer als der Maximalwert ist, wird er durch den Maximalwert usw. ersetzt.)
Antworten:
Sie könnten eine Erweiterungsmethode schreiben:
BEARBEITEN: Erweiterungsmethoden werden in statische Klassen eingeteilt. Da dies eine recht einfache Funktion ist, sollte sie wahrscheinlich in einem Kernnamespace Ihres Projekts enthalten sein. Sie können die Methode dann in jeder Codedatei verwenden, die eine using-Direktive für den Namespace enthält, z
.NET Core 2.0
Ab .NET Core 2.0 gibt es
System.Math
jetzt eineClamp
Methode, die stattdessen verwendet werden kann:quelle
IComparable
ist, dass kein Boxen auftritt. Dies sollte sehr schnell gehen. Denken Sie daran, dass die Methode mitdouble
und einer Gesamtreihenfolge entspricht, in der weniger als alle anderen Werte enthalten sind, einschließlich . Es ist also nicht gleichbedeutend mit dem Bediener. Wenn Sie einen Gleitkommatyp verwenden, müssen Sie überlegen, wie Sie ihn ebenfalls behandeln möchten . Dies ist für andere numerische Typen nicht relevant.float
CompareTo
NaN
NegativeInfinity
<
<
NaN
NaN
In beiden Fällen müssen Sie überlegen, wie Sie behandeln sollen . Die Version mit<
und>
würde die AusgabeNaN
und VerwendungNaN
fürmin
odermax
würde effektiv eine einseitige Klemme machen. MitCompareTo
würde es immer wieder kommenNaN
wenn esmax
istNaN
.Verwenden Sie einfach
Math.Min
undMath.Max
:quelle
int a0 = x > a ? x : a; return a0 < b ? a0 : b
dass (obwohl es korrekte Ergebnisse liefert) nicht gerade ideal ist.Math.Min(Math.Max(x, min), max)
ergibt sich ein Vergleich mehr als nötig, wenn x <min.Versuchen:
quelle
Es gibt keinen, aber es ist nicht zu schwer, einen zu machen. Ich habe hier eine gefunden: Klammer
Es ist:
Und es kann verwendet werden wie:
quelle
Clamp(T value, T min, T max)
Es gibt keinen im System.Math-Namespace
http://msdn.microsoft.com/en-us/library/system.math_members.aspx
Es gibt eine MathHelper-Klasse, in der sie für das XNA-Spielestudio verfügbar ist, wenn Sie dies tun:
http://msdn.microsoft.com/en-us/library/bb197892(v=XNAGameStudio.31).aspx
quelle
Teilen Sie einfach Lees Lösung mit den Problemen und Bedenken der Kommentare, wenn möglich:
Unterschiede:
ed
), um (weiter) anzuzeigen, dass der Wert nicht an Ort und Stelle geklemmt ist und stattdessen ein neuer Wert zurückgegeben wird (siehe Kommentar von @ JimBalter ).null check
für alle Eingaben geeignet (siehe Kommentar von @ JeppeStigNielsen ).min
undmax
ifmin > max
(Siehe @ JeppeStigNielsens Kommentar ).Einschränkungen: Keine einseitigen Klemmen. Wenn
max
jaNaN
, wird immer zurückgegebenNaN
(siehe Hermans Kommentar ).quelle
nameof
dass sie für C # 5 oder niedriger nicht funktioniert.Unter Verwendung der vorherigen Antworten habe ich es für meine Bedürfnisse auf den folgenden Code komprimiert. Auf diese Weise können Sie eine Zahl auch nur um ihre minimalen oder maximalen Werte klemmen.
quelle
return value.ClampedMinimum(min).ClampedMaximum(max);
?Der folgende Code unterstützt die Angabe von Grenzen in beliebiger Reihenfolge (dh
bound1 <= bound2
oderbound2 <= bound1
). Ich fand dies nützlich für Klemmwerte, die aus linearen Gleichungen (y=mx+b
) berechnet wurden, bei denen die Steigung der Linie zunehmen oder abnehmen kann.Ich weiß: Der Code besteht aus fünf superhässlichen Operatoren für bedingte Ausdrücke . Die Sache ist, es funktioniert und die folgenden Tests beweisen es. Fühlen Sie sich frei, streng unnötige Klammern hinzuzufügen, wenn Sie dies wünschen.
Sie können problemlos andere Überladungen für andere numerische Typen erstellen und die Tests grundsätzlich kopieren / einfügen.
Warnung: Der Vergleich von Gleitkommazahlen ist nicht einfach. Dieser Code implementiert
double
Vergleiche nicht robust. Verwenden Sie eine Gleitkomma-Vergleichsbibliothek, um die Verwendung von Vergleichsoperatoren zu ersetzen.xUnit / FluentAssertions-Tests:
quelle
Wenn ich den Bereich eines Arguments in [min, max] validieren möchte, verwende ich die folgende praktische Klasse:
Die Klasse funktioniert für alle Objekte, die es gibt
IComparable
. Ich erstelle eine Instanz mit einem bestimmten Bereich:Ich bestätige entweder ein Argument
oder klemmen Sie das Argument an den Bereich:
quelle