Live data from Hacker News

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

twitter.com

231–240 of 291 posts

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

#231
post #45

Earlier quoted context omitted.

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).

The expression Math.min(Math.max(num, min), max) is symmetric in min and num , so it doesn’t matter whether you interchange min and num (or, for that matter, max and num , but that is harder to see from that way to define the ‘clamp’ function)

Good point, thanks.

(Though I've just checked gcc's definition of std::clamp and it looks like

    __glibcxx_assert(!(__hi 
so order of arguments does matter there.)

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

#233
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).

It depends. (val, min, max) operates on a first argument, which is more logical as well. (min, max, val) allows range constants to be more visible if is a lenghty expression. In more powerful languages like objective-c this has less sense, as you can always specify all arguments explicitly:

  [FZUtilityManager clampIntegerValue:(NSInteger)x
                toRangeWithLowerBound:(NSInteger)min
                           upperBound:(NSInteger)max
                            withError:(out NSError **)error];
Which returns NSIntegerMax and sets the error variable if the range appears to be empty. The chance that max is NSIntegerMax is low, but if your data allows that, you can always put an additional shortcut before clamping.

  if (min > max) {
      error = [NSError errorWithDescription:@"min > max occured"];
      return NO; // or equivalent
  } else {
      x = ...
  }
  // use x

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

#234

Earlier quoted context omitted.

To me the danger of this kind of one liners is that if you use it 2 times somewhere, someone, at some point, will do the lazy refactor of “let’s put it into a function”. int clamp (int value, int min, int max) And that one liner inside. And now you have a double evaluation bomb waiting to go out on your codebase.

Why? You wrote a function, not a macro.

Accidentally overwrote the middle step:

Junior developer puts the one liner on google, finds the typical macro definition and does the change.

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

#235

Earlier quoted context omitted.

To me the danger of this kind of one liners is that if you use it 2 times somewhere, someone, at some point, will do the lazy refactor of “let’s put it into a function”. int clamp (int value, int min, int max) And that one liner inside. And now you have a double evaluation bomb waiting to go out on your codebase.

Why? You wrote a function, not a macro.

Maybe they mean that you might have been unintentionally relying on double evaluation, and then you take it away, and something breaks. Because it worked for the wrong reasons.

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

#236

Earlier quoted context omitted.

This is why computers are slow.

I was curious how slow this would be, and here is what JavaScriptCore made of this code: function clamp(n, min, max) { return [min, n, max].sort((a, b) => a - b)[1]; } for (var i = 0; i However, I was pretty disappointed when it seemed to be calling sort each time :( Perhaps I profiled it incorrectly? jsc's profiling data shows that it never hit FTL and nothing ever got inlined. The bytecode for DFG and Baseline is i…

Dude, you are generating random numbers inside the loop. That is going to dominate runtime.

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

#237

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.

I don't understand the explosion of comments here either. I was just saying for myself, it's a trivial construct and very commonly encountered.

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

#238

Is this a problem that comes up often? What kind of situation would make you want to calculate this?

It’s pretty common in data science or financial applications to restrict the range of data in this way.

There are probably SQL devs reading this and wondering what the fuss is about.

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

#239

Earlier quoted context omitted.

I was curious how slow this would be, and here is what JavaScriptCore made of this code: function clamp(n, min, max) { return [min, n, max].sort((a, b) => a - b)[1]; } for (var i = 0; i However, I was pretty disappointed when it seemed to be calling sort each time :( Perhaps I profiled it incorrectly? jsc's profiling data shows that it never hit FTL and nothing ever got inlined. The bytecode for DFG and Baseline is i…

Dude, you are generating random numbers inside the loop. That is going to dominate runtime.

I'm not testing runtime, though, I'm testing whether clamp gets optimized.

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

#240
post #165

Earlier quoted context omitted.

> 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.

It depends on what space you're working on (e.g. the https://en.wikipedia.org/wiki/Extended_real_number_line define an order on the real field union {-∞, +∞}).

Yes, but in that context, ∞ is a number. We often interpret "NaN" to mean "infinity," but it only means "not a number." Maybe I'm being pedantic, but if we want a token representing infinity as a number, it ought not be called "not a number."
Post reply on HN