Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8301226

Add clamp() methods to java.lang.Math and to StrictMath

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Fixed
    • Icon: P4 P4
    • 21
    • 21
    • core-libs
    • b10

      Quite often it's necessary to clamp a numerical value to a given
      range, using the algorithm like this:
      int clampedValue = value > max ? max : value < min ? min : value;
      or probably
      int clampedValue = Math.max(min, Math.min(max, value));
      Some examples in wild: [1] [2]

      These "algorithms" are verbose and error-prone. E.g., many years ago
      Math.max and Math.min were mixed in Jenkins CI implementation (later
      fixed in [3]). Static analyzers like SonarLint even implement a rule
      to catch such kind of mistake [4], but it cannot statically find a
      mistake if max and min values are not constant.

      Having a library method for this algorithm will make the code more
      readable, and robust. Standard libraries of various languages tend to
      implement a function that encapsulates this algorithm. E.g., Kotlin
      coerseIn [5], C# Math.Clamp [6], Rust num::clamp [7].

      I hereby propose to add a similar method to Java Math class. The
      signatures could be:
      public static int clamp(long value, int min, int max)
      public static long clamp(long value, long min, long max)
      public static double clamp(double value, double min, double max)
      public static float clamp(float value, float min, float max)

      Note that the first overload accepts a long value, so it can be used also to safely narrow a long value to int without explicit cast.

      These methods should additionally check that min is not greater than
      max (throwing IllegalArgumentException). Probably IAE should be thrown
      as well if either min or max is NaN for floating point methods. It can
      be discussed what should happen if the value is NaN (I think returning
      NaN would be ok, but throwing an exception is also a possibility).

      I can post CSR and contribute the implementation if Core Library team
      members agree that it's a good idea.

      With best regards,
      Tagir Valeev.

      [1] https://github.com/moneymod/moneymod/blob/4d2c7f5be40dbf392e75/src/main/java/wtf/moneymod/client/impl/ui/click/buttons/settings/SliderButton.java#L71
      [2] https://github.com/androidthings/experiment-expression-flower/blob/f0fd6090e0df1659bad/code/app/src/main/java/com/example/androidthings/VideoProcessor.java#L559
      [3] https://github.com/jenkinsci/jenkins/commit/e00f99251e0b
      [4] https://rules.sonarsource.com/java/RSPEC-3065
      [5] https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.ranges/coerce-in.html
      [6] https://learn.microsoft.com/en-us/dotnet/api/system.math.clamp?view=net-7.0
      [7] https://docs.rs/num/0.2.1/num/fn.clamp.html

            tvaleev Tagir Valeev
            tvaleev Tagir Valeev
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: