class Numeric

>> 1.27.million.billion
=> 1_270_000_000_000_000

>> 12873218731.to_words
=> "twelve billion, eight-hundred and seventy-three million, two-hundred and eighteen thousand, seven-hundred and thirty-one"

Works on numbers up to a googol!

Constants

BYTE_SIZE_TABLE
NAMES_LARGE

>= 100

NAMES_MEDIUM

20-90

NAMES_SMALL

< 20

Public Instance Methods

ago() click to toggle source
# File lib/epitools/core_ext/numbers.rb, line 68
def ago
  Time.now - self
end
choose(r) click to toggle source

Combinations: compute “n choose r” (self.choose®)

This represents number of ways to pick “r” items from a collection of “self” items (where the order of the items doesn't matter, and items can't be repeated.)

eg: 49.choose(6) is how many ways can we pick 6 lottery numbers from a set of 49.

Formula: n! / (r! * (n-r)!) == n * n-1 * … * n-r / r * r-1 * … * 2

# File lib/epitools/core_ext/numbers.rb, line 136
def choose(r)
  (self-r+1..self).reduce(:*) / (2..r).reduce(:*)
end
Also aliased as: combinations
clamp(range) click to toggle source

Clamp the number to a specific range

Examples:

234234234523.clamp(0..100)   #=> 100
12.clamp(0..100)             #=> 12
-38817112.clamp(0..100)      #=> 0
# File lib/epitools/core_ext/numbers.rb, line 36
def clamp(range)
  if self < range.first
    range.first
  elsif self >= range.last
    if range.exclude_end?
      range.last - 1
    else
      range.last
    end
  else
    self
  end
end
combinations(r)
Alias for: choose
commatize(char=",") click to toggle source

Convert this number to a string, adding commas between each group of 3 digits.

(The “char” argument is optional, and specifies what character to use in between

each group of numbers.)
# File lib/epitools/core_ext/numbers.rb, line 12
def commatize(char=",")
  str = self.is_a?(BigDecimal) ? to_s("F") : to_s

  int, frac = str.split(".")
  int = int.gsub /(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/, "\\1#{char}\\2"

  frac ? "#{int}.#{frac}" : int
end
from_now() click to toggle source
# File lib/epitools/core_ext/numbers.rb, line 72
def from_now
  Time.now + self
end
human_bytes(decimals=0) click to toggle source
# File lib/epitools/core_ext/numbers.rb, line 203
def human_bytes(decimals=0)
  power = self.log(1024).floor
  base  = 1024.0 ** power
  units = BYTE_SIZE_TABLE[power]
  "#{(self / base).round(decimals)}#{units}"
end
Also aliased as: human_size
human_size(decimals=0)
Alias for: human_bytes
ln() click to toggle source
# File lib/epitools/core_ext/numbers.rb, line 121
def ln
  Math.log(self)
end
log(n=nil) click to toggle source
# File lib/epitools/core_ext/numbers.rb, line 169
def log(n=nil)
  if n
    Math.log(self) / Math.log(n)
  else
    Math.log(self)
  end
end
mulmod(n) click to toggle source

Multiply self by n, returning the integer product and the floating point remainder.

# File lib/epitools/core_ext/numbers.rb, line 159
def mulmod(n)
  prod    = self * n
  intprod = prod.to_i

  [intprod, prod % intprod]
end
number?() click to toggle source
# File lib/epitools/core_ext/truthiness.rb, line 51
def number?; true; end
perms(r) click to toggle source

Permutations: compute “n P r”

This represents number of ways to pick “r” items from a collection of “self” items (where the order of the items DOES matter, and items can't be repeated.)

eg: 23.perm(3) is how many ways 23 people can win 1st, 2nd and 3rd place in a race.

Formula: n! / (n - r)!

# File lib/epitools/core_ext/numbers.rb, line 151
def perms(r)
  (self-r+1..self).reduce(:*)
end
Also aliased as: permutations
permutations(r)
Alias for: perms
things(&block) click to toggle source

If `n.times` is like `each`, `n.things` is like `map`. Return

# File lib/epitools/core_ext/numbers.rb, line 79
def things(&block)
  if block_given?
    Array.new(self, &block)
  else
    (0...self).to_a
  end
end
to_celcius() click to toggle source
# File lib/epitools/core_ext/numbers.rb, line 252
def to_celcius
  (self - 32) * 5.0 / 9.0
end
to_farenheit() click to toggle source
# File lib/epitools/core_ext/numbers.rb, line 248
def to_farenheit
  (self * 9.0 / 5.0) + 32
end
to_hms() click to toggle source

Convert seconds to hours:minutes:seconds (hours is dropped if it's zero)

# File lib/epitools/core_ext/numbers.rb, line 215
def to_hms
  seconds = self

  days,    seconds = seconds.divmod(86400)
  hours,   seconds = seconds.divmod(3600)
  minutes, seconds = seconds.divmod(60)
  seconds, frac    = seconds.divmod(1)

  result = "%0.2d:%0.2d" % [minutes,seconds]
  result = ("%0.2d:" % hours) + result   if hours > 0 or days > 0
  result = ("%0.2d:" % days)  + result   if days > 0
  result += ("." + frac.round(2).to_s.split(".").last) if frac > 0

  result
end
to_hms_in_words() click to toggle source
# File lib/epitools/core_ext/numbers.rb, line 231
def to_hms_in_words
  seconds = self

  days,    seconds = seconds.divmod(86400)
  hours,   seconds = seconds.divmod(3600)
  minutes, seconds = seconds.divmod(60)
  seconds, frac    = seconds.divmod(1)

  result = "#{seconds} sec"
  result = "#{minutes} min, " + result if minutes > 0
  result = "#{"hour".amount(hours)}, " + result if hours > 0 or days > 0
  result = "#{"day".amount(days)}, "   + result if days > 0
  # result += ("." + frac.round(2).to_s.split(".").last) if frac > 0

  result
end
to_kg() click to toggle source
# File lib/epitools/core_ext/numbers.rb, line 260
def to_kg
  self * 0.45359237
end
to_lbs() click to toggle source
# File lib/epitools/core_ext/numbers.rb, line 256
def to_lbs
  self / 0.45359237
end
to_words() click to toggle source

Convert this number to words (eg: 69 => 'sixty-nine'). Works with numbers up to a googol (10^100).

# File lib/epitools/numwords.rb, line 39
def to_words
  if is_a? Integer
    num = self
  else
    num = self.to_i
  end

  if (n = num.to_s.size) > 102
    return "more than a googol! (#{n} digits)"
  end

  whole_thing = []

  triplets = num.commatize.split(',')
  num_triplets = triplets.size

  triplets.each_with_index do |triplet, i|
    next if triplet.to_i == 0

    result = []

    tens, hunds = nil, nil

    digits = triplet.chars.to_a

    raise "Error: Not a triplet: #{triplet}" if digits.size > 3 or digits.size < 1

    if digits.size == 3
      digit = digits.shift.to_i
      hunds = NAMES_SMALL[digit] + "-hundred" if digit > 0
      digits.shift if digits.first == '0'
    end

    if digits.size == 2
      n = digits.join('').to_i

      if n > 0 and n < 20
        tens = NAMES_SMALL[n]
      elsif n > 0
        tens = NAMES_MEDIUM[digits.shift.to_i - 2]
        if digits.first != '0'
          tens += "-" + NAMES_SMALL[digits.shift.to_i]
        else
          digits.shift
        end
      end
    end

    if digits.size == 1
      n = digits.join('').to_i
      tens = NAMES_SMALL[n] if n > 0
    end

    if hunds
      if tens
        result << "#{hunds} and #{tens}"
      else
        result << hunds
      end
    else
      result << tens if tens
    end

    magnitude = (num_triplets - i)
    result << NAMES_LARGE[magnitude-2] if magnitude > 1

    whole_thing << result.join(' ') if result.any?
  end

  whole_thing.join ', '
end
truthy?() click to toggle source
# File lib/epitools/core_ext/truthiness.rb, line 49
def truthy?; self > 0; end
underscorize() click to toggle source

Convert this number to a string, adding underscores between each group of 3 digits.

# File lib/epitools/core_ext/numbers.rb, line 24
def underscorize
  commatize("_")
end