Live data from Hacker News

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

twitter.com

211–220 of 291 posts

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

#211
Most of the ternary implementations here are less correct than the original. You generally want min/max to satisfy the following:

1. min/max of NaN and anything is NaN

2. negative 0 is strictly smaller than positive 0

it's a fun exercise to implement clamp under these constraints.

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

#212
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)

Assuming we know (lower_bound Math.max(lower_bound, Math.min(num, upper_bound)) Since i read right to left.

It’s amazing what a difference it makes when you just good names and formatting

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

#213
I find the following much easier to read. It's certainly easier to maintain, deal with, for successive programmers, and likely has exactly the same compiled/interpreted operations for most common languages. Optionally replace t1 and t2 by overwriting num if needed.

Use full if else if you must.

If you're worried about speed, using built in min and max is not a good idea. There are many, many tricks to remove branches for certain datatypes, etc., as you need.

var t1 = num < min ? min : num; // clamp to min var t2 = max < t1 ? max : t1; // clamp to max return t2; // num clamped to [min,max]

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

#214
post #132

Kotlin provides pretty nice syntax sugar for that: num.coerceIn(min..max) That's it. This human reader finds it considerably more readable. It also has coerceAtLeast and coerceAtMost

This is what I love about kotlin. The standard library has a good coverage of these kinds of problems and it is done in a simple an clean way. I had the same feeling with Python, the language got you cover with mundane tasks and you don't have to spend time researching libs that do it for you (or spend your time doing a clamp implementation + tests).

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

#216
post #118

Earlier quoted context omitted.

Does NaN have an "order" in the set of reals or integers or whatever? I would have no idea what to expect from `min(NaN, x)` or max same. But is it specified by an IEEE standard or something?

Both min and max should return NaN, if any of their parameters is NaN. Sorting can be defined where to place the NaNs (head/tail) but it's largely irrelevant in this case as simply the substitution won't be permitted by any compiler. NaN is part of IEEE754 but of course it's not a 'real' number (integer numbers don't have NaNs) Edit: you can consider NaN (and to a degree both infinities) as an exception, once it occu…

> Both min and max should return NaN, if any of their parameters is NaN.

That's not a given, though. IEEE 754-2008 defined min and max as returning the non-NaN parameter. They have been removed in IEEE 754-2019 though.

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

#217
post #116
post #23

Earlier quoted context omitted.

[min, num, max].sort()[1] I really love this! I’m not sure whether to laugh, cry, or applaud, but I love how it makes me feel all those emotions at the same time.

I also think the fact it doesn't work in JS (due to sort defaulting to alphabetical sort) brings in even more appropriate emotions.

    [10, 2, 100].sort()[1] //returns 100

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

#218
post #109
post #75

Earlier quoted context omitted.

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)

this doesn't work for NaN, e.g {0d, Double.NaN, 1d} returns 1d.

Having a NaN at that point feels like a bug anyway, the solution is probably to check the arguments and throw an exception if NaN is provided (or use an input type that doesn't allow invalid values)

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

#219

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.

C++17 does have it... but it doesn't compile optimally. It compiles to something based on comparisons instead of the floating-point-specific operations. I tried this on a number of compiler combinations and didn't see anything that would emit min/max instructions for `std::clamp `. https://www.godbolt.org/z/MKqTvE

Your two functions are not equivalent. std::fmax handles NaN, but std::clamp does not.

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

#220

Once you've seen this a few dozen times, you instantly parse it as "clamp(num, min, max)"

Did a bunch of coding bootcamps just begin session or something? I don't understand the comments here treating it like it's so hard to write and verify that it needs a completely different, slower, less direct, cutesy implementation.
Post reply on HN