66

假设我有一个value,我通常这样做是为了将它“钳制”到一个范围,这里是 range [0..1]。也就是说,如果它低于范围开始,则将其增加到范围开始,高于范围结束,将其减小到范围结束。

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

是否有任何内置函数可以限制在某个范围内?

4

5 回答 5

180

是否有任何内置函数可以限制在某个范围内?

不。

于 2013-05-20T19:14:22.530 回答
51

查看了另一个答案中提供的通用钳位方法后,值得注意的是,这对原始类型有装箱/拆箱注意事项。

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

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

这将使用Float包装类,产生 3 个装箱操作,每个参数一个,以及返回类型的 1 个拆箱操作。

为避免这种情况,我会坚持长期编写或对您想要的类型使用非泛型函数:

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

然后只需为您需要的每种原始类型使用相同的方法重载即可。

于 2013-05-20T22:06:53.490 回答
25

Guava包括Ints.constrainToRange()(以及其他原语的等效方法)。从发行说明

添加了将给定值约束到由和值constrainToRange([type] value, [type] min, [type] max)定义的封闭范围的方法。如果它在范围内,它们返回值本身,如果它低于范围,如果它高于范围。minmaxminmax

于 2017-03-23T05:56:08.627 回答
17

移植自.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;
}

注意:与 .NET 不同,泛型中不允许使用原始类型,这意味着它们必须被装箱/拆箱。当使用原始类型(例如intand double)时,此实现将执行三个装箱操作和一个拆箱操作。

注意:因为它是.NET answer的一个端口,所以我将其设为社区 wiki 帖子。

于 2013-05-20T19:35:33.813 回答
7

另一个不太漂亮但可能的解决方案是使用三元运算符,它是if-then-else语句的简写。

一些例子:

// 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;
于 2018-08-29T15:00:23.670 回答