0

I have a calculation that may return a negative value. In that case, I want to limit the lowest return value to 0.

a - b
> -1

To get the desired result, I know I can place that calculation in an array with 0 and retrieve the highest value:

[0, a - b].max
> 0

I thought that there was a method on Integer that could do this (I was thinking of #floor but that does something different.) I've taken a look at the documentation but I can't find a method that does what I want and I feel that I must have missed something. Is there a method that returns the result I want? Is there a better way than the one I've suggested?

user3574603
  • 3,364
  • 3
  • 24
  • 59
  • 3
    Yep, `[0, a - b].max` is the most elegant I can think of right now. – Sergio Tulentsev Dec 29 '18 at 00:13
  • 2
    Easy, `(a - b).to_s.sub(/-.*/, '0').to_i` (please don't) – Marcin Kołodziej Dec 29 '18 at 00:16
  • 1
    There's [`clamp`](http://ruby-doc.org/core/Comparable.html#method-i-clamp) but it requires both, a lower and an upper bound. – Stefan Dec 29 '18 at 00:16
  • `a >= b ? (a-b) : 0` is really the only alternative (and it arguably reads better), but I think most Rubyists (other than @Marcin) would go with `[0, a-b].max`, though neither seem to me to be especially *elegant*. – Cary Swoveland Dec 29 '18 at 00:20
  • `v.negative? ? 0 : v` – Sagar Pandya Dec 29 '18 at 00:35
  • 1
    @Stefan You could `i.clamp(0, i.abs)` if you really want to use `clamp` but that feels a bit contrived and overly clever, shame that `clamp` doesn't take a range so you could `i.clamp(0..)` (in Ruby 2.6). – mu is too short Dec 29 '18 at 00:44
  • `(num+num.abs)/2` – steenslag Dec 29 '18 at 00:59
  • `num.rect.max` if you're never using complex numbers. or `num.coerce(0).max` – Tom Dec 29 '18 at 02:16
  • @ Marcin Kołodziej :,( – sammms Dec 29 '18 at 05:37
  • If this were me, I'd do it in two lines: `v = a - b` and `v = 0 if v < 0`. It feels the most straight forward and I would probably put a comment above the second line explaining why I'm setting it to 0 if it's negative. I tend to put more weight in readability and less in code golfing. I would also recommend avoiding creating unnecessary arrays for performance reasons. – Nate Dec 29 '18 at 05:43
  • Be zero unless you are a natural number, just for :), `v = 0 unless (1..Float::INFINITY).include? v`, or `v = 0 unless v > 0`. But why all answering in comments? – iGian Dec 29 '18 at 06:48
  • See my solution to the original post this was marked a duplicate of. I think your solution is essentially correct, and probably the most readable besides a small refactor. I might change it slightly like so: `def total final_total = subtotal - discount; [final_total, 0].max end` Once you see this max expression once or twice you can read it as follows: "final_total, but at least zero". See my solution to the original post this was marked a duplicate of. – Rex Butler Dec 29 '18 at 17:31
  • 1
    @muistooshort _"shame that clamp doesn't take a range"_ – or keyword arguments, i.e. `clamp(min: 0)` ... maybe I should file a feature request. – Stefan Dec 29 '18 at 19:08
  • @Stefan I was looking at the `cmp_clamp` source in `compar.c` yesterday to see what would be involved in patching it. I don't know if I could handle editing it without fixing the insane and inconsistent mess of mixed spaces and tabs and tabstops for the indentation. – mu is too short Dec 29 '18 at 19:22

0 Answers0