Class: Numeric

Inherits:
Object show all
Defined in:
lib/nuggets/numeric/limit.rb,
lib/nuggets/numeric/signum.rb,
lib/nuggets/numeric/duration.rb,
lib/nuggets/numeric/to_multiple.rb

Overview

#

nuggets – Extending Ruby #

#

Copyright © 2007-2011 Jens Wille #

#

Authors: #

Jens Wille <[email protected]>                                       #
                                                                        #

nuggets is free software; you can redistribute it and/or modify it under # the terms of the GNU Affero General Public License as published by the Free # Software Foundation; either version 3 of the License, or (at your option) # any later version. #

#

nuggets is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for # more details. #

#

You should have received a copy of the GNU Affero General Public License # along with nuggets. If not, see <www.gnu.org/licenses/>. #

#

++

Instance Method Summary collapse

Instance Method Details

#ceil_to(target) ⇒ Object

call-seq:

num.ceil_to(target) => aNumeric

Returns the smallest multiple of target greater than or equal to num.



57
58
59
# File 'lib/nuggets/numeric/to_multiple.rb', line 57

def ceil_to(target)
  to_multiple_of(target, :ceil)
end

#floor_to(target) ⇒ Object

call-seq:

num.floor_to(target) => aNumeric

Returns the largest multiple of target less than or equal to num.



49
50
51
# File 'lib/nuggets/numeric/to_multiple.rb', line 49

def floor_to(target)
   to_multiple_of(target, :floor)
end

#hmsObject

call-seq:

num.hms => anArray

Converts num into hour, minute, and second portions.

Raises:

  • (::ArgumentError)


33
34
35
36
37
38
39
40
# File 'lib/nuggets/numeric/duration.rb', line 33

def hms
  raise ::ArgumentError, "negative duration #{self}" if self < 0

  one_minute = 60
  one_hour   = 60 * one_minute

  [((h,) = divmod(one_hour)).last.divmod(one_minute), h].reverse.flatten  # *SCNR* ;-)
end

#limit(min, max) ⇒ Object Also known as: between

call-seq:

num.limit(min, max) => aNumeric

Returns min if that’s larger than num, or max if that’s smaller than num. Otherwise returns num.



34
35
36
37
38
# File 'lib/nuggets/numeric/limit.rb', line 34

def limit(min, max)
  min, max = max, min if max < min

  min(min).max(max)
end

#max(max) ⇒ Object Also known as: at_most

call-seq:

num.max(max) => aNumeric

Returns num or max, whatever is smaller.



56
57
58
# File 'lib/nuggets/numeric/limit.rb', line 56

def max(max)
  self > max ? max : self
end

#min(min) ⇒ Object Also known as: at_least

call-seq:

num.min(min) => aNumeric

Returns num or min, whatever is larger.



46
47
48
# File 'lib/nuggets/numeric/limit.rb', line 46

def min(min)
  self < min ? min : self
end

#negative?Boolean

Returns:

  • (Boolean)


33
34
35
# File 'lib/nuggets/numeric/signum.rb', line 33

def negative?
  self < 0
end

#non_negative?Boolean

Returns:

  • (Boolean)


37
38
39
# File 'lib/nuggets/numeric/signum.rb', line 37

def non_negative?
  !negative?
end

#positive?Boolean

Returns:

  • (Boolean)


29
30
31
# File 'lib/nuggets/numeric/signum.rb', line 29

def positive?
  self > 0
end

#round_to(target) ⇒ Object

call-seq:

num.round_to(target) => aNumeric

Rounds num to the nearest multiple of target.



41
42
43
# File 'lib/nuggets/numeric/to_multiple.rb', line 41

def round_to(target)
   to_multiple_of(target, :round)
end

#signumObject Also known as: sign, sgn

call-seq:

num.signum => -1, 0, 1

Returns the sign of num.



45
46
47
48
# File 'lib/nuggets/numeric/signum.rb', line 45

def signum
  # http://weblog.jamisbuck.org/2015/8/5/reducing-a-number-to-its-sign.html
  self <=> 0
end

#signum_s(positive = '+', negative = '-', zero = positive) ⇒ Object Also known as: sign_s, sgn_s



53
54
55
# File 'lib/nuggets/numeric/signum.rb', line 53

def signum_s(positive = '+', negative = '-', zero = positive)
  [zero, positive, negative][signum]
end

#to_hms(precision = 0, labels = %w[h m s],, time = hms) ⇒ Object

call-seq:

num.to_hms([precision[, labels]]) => aString

Produces a stringified version of num’s time portions (cf. #hms), with the specified precision for the seconds (treated as floating point). The individual parts are labelled as specified in the labels parameter (hours, minutes, seconds in that order). Leading parts with a value of zero are omitted.

Examples:

180.to_hms               #=> "3m0s"
180.75.to_hms            #=> "3m1s"
180.75.to_hms(2)         #=> "3m0.75s"
8180.to_hms              #=> "2h16m20s"
8180.to_hms(0, %w[: :])  #=> "2:16:20"


74
75
76
77
78
79
80
81
# File 'lib/nuggets/numeric/duration.rb', line 74

def to_hms(precision = 0, labels = %w[h m s], time = hms)
  h, m, s = time

  h.zero? ? m.zero? ?
    "%0.#{precision}f#{labels[2]}" % [s] :
    "%d#{labels[1]}%0.#{precision}f#{labels[2]}" % [m, s] :
    "%d#{labels[0]}%d#{labels[1]}%0.#{precision}f#{labels[2]}" % [h, m, s]
end

#to_multiple_of(target, what = :round) ⇒ Object

call-seq:

num.to_multiple_of(target, what) => aNumeric

Returns the nearest multiple of target according to what.



33
34
35
# File 'lib/nuggets/numeric/to_multiple.rb', line 33

def to_multiple_of(target, what = :round)
  target.zero? ? self : (to_f / target).send(what) * target
end

#to_ymd(include_hms = false, labels = %w[y m d])) ⇒ Object

call-seq:

num.to_ymd([include_hms[, labels]]) => aString

Produces a stringified version of num’s date portions (cf. #ymd), analogous to #to_hms. Includes time portions (cf. #hms) if include_hms is true.



89
90
91
92
93
94
95
96
97
98
# File 'lib/nuggets/numeric/duration.rb', line 89

def to_ymd(include_hms = false, labels = %w[y m d])
  unless include_hms
    to_hms(0, labels, ymd)
  else
    y, m, d = ymd
    e = d.truncate

    "#{to_hms(0, labels, [y, m, e])} #{((d - e) * 24 * 60 * 60).to_hms}"
  end
end

#ymdObject

call-seq:

num.ymd => anArray

Converts num into year, month, and day portions.

Raises:

  • (::ArgumentError)


46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/nuggets/numeric/duration.rb', line 46

def ymd
  raise ::ArgumentError, "negative duration #{self}" if self < 0

  one_day   = 24 * 60 * 60
  one_month = 30 * one_day
  one_year  = 365.25 * one_day

  y, m = divmod(one_year)
  m, d = m.divmod(one_month)

  [y, m, d / one_day]
end