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.
211–220 of 291 posts
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.
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.
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]
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
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…
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.
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 100Earlier 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.
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
Once you've seen this a few dozen times, you instantly parse it as "clamp(num, min, max)"