Does java have a clamp function?
Asked Answered
A

7

83

Suppose I have a value, I usually do this to "clamp" it to a range, here the range [0..1]. That is if it is below the range start, increase it to the range start, it above the range end, reduce it to the range end.

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

Is there any built in function for clamping to a range?

About answered 20/5, 2013 at 19:11 Comment(7)
@LuiggiMendoza HLSLAbout
See #2683942 ?Ignominious
@LuiggiMendoza Also OpenGLAbout
@AdamGent thanks, but that's c#About
@About it looks pretty trivial to write your own (ie just translate the c#).Ignominious
@AdamGent It's clearly trivial to right my own function, I have the code right in the question there. I'd rather use one that's built in, particularly because that would deal with all value datatypes probably.About
I don't really know your level of expertise java so it's hard for me to assume your knowledge. The c # uses Comparable to handle multiple data types.... Guess what you do in Java :)Ignominious
M
16

Yes, it's built in from Java 21.

Overloads are provided for float, double, int and long.

Myke answered 11/3, 2023 at 17:40 Comment(0)
M
199

Edit, fall 2023: this answer is obsolete! Please see this much-more-recent answer for information as of Java 21.


Is there any built in function for clamping to a range?

No.

Matheny answered 20/5, 2013 at 19:14 Comment(1)
For future visitors: this is changing. See Michael Berry's answer.Postage
A
56

Having looked at the generic clamp method offered up in another answer, it is worth noting that this has boxing/unboxing considerations for primitive types.

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

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

This will use the Float wrapper class, resulting in 3 box operations, one for each parameter, and 1 unbox operation for the returned type.

To avoid this, I would just stick to writing it long hand or use a non-generic function for the type you want:

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

Then just overload with identical methods for every primitive type you require.

About answered 20/5, 2013 at 22:6 Comment(0)
B
28

Guava includes Ints.constrainToRange() (and equivalent methods for the other primitives). From the release notes:

added constrainToRange([type] value, [type] min, [type] max) methods which constrain the given value to the closed range defined by the min and max values. They return the value itself if it's within the range, the min if it's below the range and the max if it's above the range.

Bitumen answered 23/3, 2017 at 5:56 Comment(2)
For those that use Apache commons lang3 and not Guava, there is the Range.fit method. Range.between(0.0, 1.0).fit(0.5); // returns 0.5Kitti
They added this in 3.10: commons.apache.org/proper/commons-lang/…Lineberry
I
16

Ported from a .NET answer:

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

Caution: Unlike .NET, primitive types are not allowed in generics, which means they must be boxed/unboxed. When working with primitive types, such as int and double, this implementation will perform three box operations and one unbox operation.

Note: since it’s a port of the .NET answer, I made this a community wiki post.

Ignominious answered 20/5, 2013 at 19:11 Comment(0)
M
16

Yes, it's built in from Java 21.

Overloads are provided for float, double, int and long.

Myke answered 11/3, 2023 at 17:40 Comment(0)
Z
14

Another not so pretty, but possible solution is to use the ternary operator, which is a shorthand for the if-then-else statement.

Some Examples:

// 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;
Zavras answered 29/8, 2018 at 15:0 Comment(2)
I like this one-liner. It's concise!Ils
I ran several thousand iterations of this, versus the original method provided by @About and this seems to be taking about 3/4ths of the time to calculate. Definitely more efficient than using Min/Max functions.Flamenco
I
2

This may be unrelated to the question, but if someone's looking for the same feature in javafx or kotlin, as I was, here they are:

javafx:

Utils.clamp(min, value, max)

kotlin:

value.coerceIn(min, max)
Insulation answered 6/6, 2023 at 9:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.