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
# File lib/epitools/core_ext/numbers.rb, line 68 def ago Time.now - self end
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
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
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
# File lib/epitools/core_ext/numbers.rb, line 72 def from_now Time.now + self end
# 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
# File lib/epitools/core_ext/numbers.rb, line 121 def ln Math.log(self) end
# 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
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
# File lib/epitools/core_ext/truthiness.rb, line 51 def number?; true; end
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
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
# File lib/epitools/core_ext/numbers.rb, line 252 def to_celcius (self - 32) * 5.0 / 9.0 end
# File lib/epitools/core_ext/numbers.rb, line 248 def to_farenheit (self * 9.0 / 5.0) + 32 end
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
# 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
# File lib/epitools/core_ext/numbers.rb, line 260 def to_kg self * 0.45359237 end
# File lib/epitools/core_ext/numbers.rb, line 256 def to_lbs self / 0.45359237 end
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
# File lib/epitools/core_ext/truthiness.rb, line 49 def truthy?; self > 0; end
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