Earlier quoted context omitted.
> in desktop edition of the runtime huh?
MS .NET framework. Unfortunately, for the last couple years it lags behind .NET core. Even 2 years old .NET core 2.1 is better in some regards than the latest desktop version 4.8.
Math.min(Math.max(num, min), max)
261–270 of 291 posts
Re: Math.min(Math.max(num, min), max)
#262Earlier quoted context omitted.
Your two functions are not equivalent. std::fmax handles NaN, but std::clamp does not.
Depends on how the comparisons are ordered. Some of the orderings I've seen in here do respect NaN by virtue of `x > upper_bound` comparing false if either x or upper_bound are NaN.
Re: Math.min(Math.max(num, min), max)
#263> it takes me ages to convince myself this implementation is correct It would take them less time to convince themself if they switched min and num to put the values in proper semantic order: min Math.min(Math.max(min, num), max)
That still leaves the order of Math.min and Math.max undecided and will probably not help much if you get easily confused by the visuals of this code. I never thought about it but of course there must be code tongue twisters (or more correctly, brain twisters). Thinking about it, I would probably go with a less confusing implementation. Terse code is hard to read and the compiler is likely clever enough to choose the…
Not in my experience. The compiler is likely to be able to do something decent to it, but it'll probably be different.
Consider the following snippets. For unsigned integers they're all equivalent (and return the max of x and m), but gcc with a wide range of flags can't recognize them as identical.
(x=m) * x
(xRe: Math.min(Math.max(num, min), max)
#264Earlier 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)
Beware that in JavaScript, the language that this tweet is about, the sort function sorts alphabetically by default. [100, 10, 11].sort()[1] === 100
BRB, just checking some code…
Re: Math.min(Math.max(num, min), max)
#265Earlier quoted context omitted.
You know what's great about that? The order of the arguments doesn't matter. So all the debate about "should it be num, min, max or min, num, max"- your solution does not care. Put them in any order you like! You've redefined the problem from clamping a given value into picking the middle value from 3. This is a lovely way to re-interpret it.
Well, the order of the arguments does matter. Sorting three values requires 2.67 comparisons where clamping a value between two other values requires exactly 2. There are plenty of contexts where cleverly avoiding a problem by doing 33% more work isn't viewed as desirable.
Re: Math.min(Math.max(num, min), max)
#266 (min + ((num + max - Math.abs(num - max)) / 2) + Math.abs(min - ((num + max - Math.abs(num - max)) / 2))) / 2
Since min(a, b) = (a + b - |a - b|) / 2
and max(a, b) = (a + b + |a - b|) / 2Re: Math.min(Math.max(num, min), max)
#267>[...] 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?
Re: Math.min(Math.max(num, min), max)
#268Earlier quoted context omitted.
this doesn't work for NaN, e.g {0d, Double.NaN, 1d} returns 1d.
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?
Re: Math.min(Math.max(num, min), max)
#269OPs implementation requires 2 comparisons. I think this C expression is clearer, and will sometimes use 1 comparison: num max ? max : num
Branching is the expensive part, not comparisons.
This is one of those cases where I think it is much more readable to just write the code than to puzzle over what Math.min(Math.max(min, num), max); might be doing.
if (num max)
return max;
return num;
That's how I'd write it. May not be super terse, but anyone that stumbles on this will know precisely what's happening without needing to take a few seconds to puzzle things out.Re: Math.min(Math.max(num, min), max)
#270Earlier quoted context omitted.
Absolutely. With the above implementation, I can see exactly what's going on, with the others, I'm trying to work out potential edge cases.
I prefer the min/max-based definition for the same reason: Its easier to work out the edge cases around NaN and comparisons against NaN.
That doesn't seem unreasonable. (In fact, that's what happens with the min/max approach).