Live data from Hacker News

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

twitter.com

151–160 of 291 posts

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

#151
post #147

I think the main hurdle is that we need to read this inside-out, which is something we face regularly trying to read nested function calls. I seriously believe pipe-like operators solve this problem cleanly. In Elixir which does have the pipe `|>` this could be. number = number |> max(lower_bound) |> min(upper_bound) Which IMO is quite elegant.

Note: I don't really know Elixir, all I know is that this works in repl.it

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

#152
post #103

Earlier quoted context omitted.

At the risk of starting a style debate, this may be easier to read if you write it like an if-else: a > max ? max : a

Unless, of course, your language "designer" has no idea why every other language uses right-associative ternary operators.

This was a "fun" bug to track down in a PHP codebase.

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

#153
post #128

68K assembly, no branches: # d0 = num, d1 = low, d2 = high, d3 = scratch sub.l d1, d0 subx.l d3, d3 or.l d3, d0 addx.l d1, d0 # d0 = max(num,low) sub.l d2, d0 subx.l d3, d3 and.l d3, d0 add.l d2, d0 # d0 = min(max(num,low),high) Adapted from "Superoptimizer -- A Look at the Smallest Program" by Henry Massalin [1]. [1] https://web.stanford.edu/class/cs343/resources/superoptimize...

Note that with modern branch predictors such optimizations may not actually be beneficial–ARM got rid of condition codes on all its instructions in the 64-bit version. (Plus, I assume they ran out of space to encode them.)

IEEE754 has defined min and max for quite some time. Nowadays almost all FPUs have min and max instructions built-in.

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

#154
post #109

Earlier 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?

No, it breaks the ordering requirements. NaN compares greater than and less than every number.

You can say that a call to max should return NaN if any argument is NaN, but you can't say the same about sorting. (For one thing... sorting an array doesn't return a scalar value.) Sorting is done with comparisons, and what happens if a NaN gets into the list of values will depend on which specific comparisons happen to be done.

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

#155
post #109

Earlier 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?

> Does NaN have an "order" in the set of reals or integers or whatever?

By definition, something that is not a number (real, integer, etc.) cannot be compared to something that is a number.

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

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

I find the extra words wordy.

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

#157

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

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

#158

Earlier quoted context omitted.

no idea what's going on there, I know some of those variables are actually functions but the whole thing is unreadable unless you have experience in haskell imo

The backticks turn regular functions into left-associative operators of the highest priority (by default). So a `foo` b `bar` c is (bar (foo a b) c)

Oohh nice. So kinda like a pipe.

I really think we deserve more syntax that allowed something like this, because otherwise one needs to read `(bar (foo a b) c)` inside-out.

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

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

I think some of us (most? all?) develop a tendency to act/be clever instead of act/be clear. When I resist that temptation, I ask for something like:

    clamped(num, range=[ lower_bound, upper_bound ]);
and then have no interest in how this actually gets implemented.
Post reply on HN