Live data from Hacker News

Math.min(Math.max(num, min), max)

twitter.com

241–250 of 291 posts

Re: Math.min(Math.max(num, min), max)

#241
post #75
post #28

I find that the fact that the functions min and max have the same name as the variables min and max increases cognitive load which makes it harder to think about it. I find the following easier to read : Math.min(Math.max(num, lower_bound), upper_bound)

Easy to remember, but may take some time to grasp: Arrays.sort( {lower_bound, num, upper_bound} )[1]; Next challenge: teach the optimizer to make that almost as fast as the min/max way ;-) (You can’t reduce it to the min/max call because it also works if you accidentally pass a lower bound that’s larger than the upper bound. Worst-case, the above takes 3 comparisons, unless at least two of the inputs are constants)

Beware that in JavaScript, the language that this tweet is about, the sort function sorts alphabetically by default.

    [100, 10, 11].sort()[1] === 100

Re: Math.min(Math.max(num, min), max)

#242
post #7

Stage 1 ECMAScript proposal to add Math.clamp (among others): https://github.com/rwaldron/proposal-math-extensions But it looks dead: https://github.com/rwaldron/proposal-math-extensions/issues/... As someone mentioned in the thread, nested ternary is easier to interpret: (a > max ? max : (a < min ? min : a))

To each his own but I disagree. Nested ternary's are hard to read and understand, and modifying them (by future devs) is tricky and error prone.

True, nested ternaries can be hard to follow. And the excessive parentheses promote this way of looking at it.

OTOH I think chained ternaries can be simple and easy to understand.

Yes, they are the exact same thing in this case, but getting rid of those nested parens really helps, at least for me.

sarah180's example is a good illustration. I would change the order of the tests because it makes more sense to me to check the min before the max. I'd also make one minor formatting change, because I code in a proportional font and can't line things up in columns:

  a  max ? max :
  a
Maybe people think differently, but to me that is super easy to understand, and much better than the confusing Math.min/max stuff.

I would also wrap the whole thing inside a function:

  function clamp( value, min, max ) {
      return(
          value  max ? max :
          value
      );
  }
Now that it's inside a function, you could change the code to use if statements, or Math.min/max, or whatever suits your preferences.

Re: Math.min(Math.max(num, min), max)

#244
I find the following easier to visualize. If L is the lower bound and U is the upper bound, and if you visualize L, U as two points on the real number line, then:

left_of_U ( right_of_L (num)) = right_of_L ( left_of_U (num)) = clamped version of num between L and U.

Here, left_of_U = Math.min(num, U) and right_of_L = Math.max(num, L).

Re: Math.min(Math.max(num, min), max)

#245

>[...] it takes me ages to convince myself this implementation is correct. Is that supposed to be difficult? Not trying to be snarky, I'm honestly surprised, do people actually struggle with this? Googlers in particular?

This whole discussion feels like I‘m not getting an obvious joke.

Re: Math.min(Math.max(num, min), max)

#246
post #28

I find that the fact that the functions min and max have the same name as the variables min and max increases cognitive load which makes it harder to think about it. I find the following easier to read : Math.min(Math.max(num, lower_bound), upper_bound)

It’s usually nicer to make a helper function: const clamp = (x, low, high) => Math.max(low, Math.min(x, high)); Then it can be easily used later via a descriptive name. e.g. color_component = clamp(color_component, 0, 255);

[deleted]

Re: Math.min(Math.max(num, min), max)

#248
post #45

In languages I use there’s usually no need to write that code. C++/17 has std::clamp() in header. Modern C# has Math.Clamp() since .NET Core 2.0; too bad it’s not available in desktop edition of the runtime. HLSL has clamp() intrinsic function, and a special version saturate() to clamp into [ 0 .. +1 ] interval.

It gets a bit confusing when the order of arguments is different depending on the library. For instance, with std it's std::clamp(val, min, max), but with Qt it's qBound(min, val, max) (for some reason I think the order of arguments in qBound is more logical).

A good text editor solves this problem. I can vouch for emacs, but I would be shocked if there weren't a good way to get vim to do this for you.

The list of hard programming things is long; things that are trivially solved by a tool shouldn't be in the list.

Post reply on HN