web-dev-qa-db-fra.com

Java a-t-il une fonction de serrage?

Supposons que j'ai un value, je le fais habituellement pour le "fixer" à une plage, ici la plage [0..1]. C'est-à-dire s'il est en dessous du début de plage, l'augmenter jusqu'au début de plage, au-dessus de la fin de plage, le réduire jusqu'à la fin de plage.

clampedValue = Math.max(0, Math.min(1, value));

Existe-t-il une fonction intégrée pour le serrage sur une plage?

51
weston

Après avoir examiné la méthode de serrage générique proposée dans une autre réponse, il convient de noter que cela a boxing/unboxing considérations pour les types primitifs.

public static <T extends Comparable<T>> T clamp(T val, T min, T max) {...}

float clampedValue = clamp(value, 0f, 1f);

Cela utilisera la classe wrapper Float, résultant en 3 opérations de boîte, une pour chaque paramètre et 1 opération de déballage pour le type renvoyé.

Pour éviter cela, je me contenterais de l'écrire à la main ou d'utiliser une fonction non générique pour le type que vous souhaitez:

public static float clamp(float val, float min, float max) {
    return Math.max(min, Math.min(max, val));
}

Ensuite, surchargez avec des méthodes identiques pour chaque type primitif dont vous avez besoin.

42
weston

Existe-t-il une fonction intégrée pour le serrage sur une plage?

Non.

154
Matt Ball

Depuis la version 21, Guava inclut Ints.constrainToRange() (et méthodes équivalentes pour les autres primitives). À partir de notes de version :

ajout de méthodes constrainToRange([type] value, [type] min, [type] max) qui contraignent la valeur donnée à la plage fermée définie par les valeurs min et max. Ils renvoient la valeur elle-même si elle est dans la plage, le min s'il est en dessous de la plage et le max s'il est au-dessus de la plage.

17
dimo414

Porté depuis ne réponse .NET :

public static <T extends Comparable<T>> T clamp(T val, T min, T max) {
    if (val.compareTo(min) < 0) return min;
    else if (val.compareTo(max) > 0) return max;
    else return val;
}

Attention: Contrairement à .NET, les types primitifs ne sont pas autorisés dans les génériques, ce qui signifie qu'ils doivent être encadrés/non encadrés. Lorsque vous travaillez avec des types primitifs, tels que int et double, cette implémentation effectuera trois opérations de boîte et une opération de déballage.

Remarque: comme il s'agit d'un port de la réponse .NET , j'ai créé ce message sur un wiki communautaire.

15
Adam Gent

Une autre solution pas si jolie, mais possible est d'utiliser l'opérateur ternaire, qui est un raccourci pour le if-then-else déclaration.

Quelques exemples:

// value must be between MIN_VALUE and MAX_VALUE
value = value > MAX_VALUE ? MAX_VALUE : value < MIN_VALUE ? MIN_VALUE : value;

// value must be between 0 and 10
value = value > 10 ? 10 : value < 0 ? 0 : value;
2
HugoTeixeira