Class: Strings::Numeral

Inherits:
Object
  • Object
show all
Defined in:
lib/strings/numeral.rb,
lib/strings/numeral/version.rb,
lib/strings/numeral/extensions.rb,
lib/strings/numeral/configuration.rb

Defined Under Namespace

Modules: Extensions Classes: Configuration, Error

Constant Summary collapse

NEGATIVE =
"negative"
HUNDRED =
"hundred"
ZERO =
"zero"
AND =
"and"
POINT =
"point"
SPACE =
" "
CARDINALS =
{
  0 => "",
  1 => "one",
  2 => "two",
  3 => "three",
  4 => "four",
  5 => "five",
  6 => "six",
  7 => "seven",
  8 => "eight",
  9 => "nine",
  10 => "ten",
  11 => "eleven",
  12 => "twelve",
  13 => "thirteen",
  14 => "fourteen",
  15 => "fifteen",
  16 => "sixteen",
  17 => "seventeen",
  18 => "eighteen",
  19 => "nineteen",
  20 => "twenty",
  30 => "thirty",
  40 => "forty",
  50 => "fifty",
  60 => "sixty",
  70 => "seventy",
  80 => "eighty",
  90 => "ninety",
}.freeze
CARDINAL_TO_SHORT_ORDINAL =
{
  0 => "th",
  1 => "st",
  11 => "th",
  2 => "nd",
  12 => "th",
  3 => "rd",
  13 => "th",
  4 => "th",
  5 => "th",
  6 => "th",
  7 => "th",
  8 => "th",
  9 => "th"
}.freeze
CARDINAL_TO_ORDINAL =
{
  "zero" => "zeroth",
  "one" => "first",
  "two" => "second",
  "three" => "third",
  "four" => "fourth",
  "five" => "fifth",
  "six" => "sixth",
  "seven" => "seventh",
  "eight" => "eighth",
  "nine" => "ninth",
  "ten" => "tenth",
  "eleven" => "eleventh",
  "twelve" => "twelfth",
  "thirteen" => "thirteenth",
  "fourteen" => "fourteenth",
  "fifteen" => "fifteenth",
  "sixteen" =>  "sixteenth",
  "seventeen" =>  "seventeenth",
  "eighteen" =>  "eighteenth",
  "nineteen" =>  "nineteenth",
  "twenty" =>  "twentieth",
  "thirty" =>  "thirtieth",
  "forty" => "fortieth",
  "fifty" => "fiftieth",
  "sixty" => "sixtieth",
  "seventy" => "seventieth",
  "eighty" => "eightieth",
  "ninety" => "ninetieth"
}.freeze
CARDINAL_TO_ROMAN =
{
  1 => "I",
  4 => "IV",
  5 => "V",
  9 => "IX",
  10 => "X",
  40 => "XL",
  50 => "L",
  90 => "XC",
  100 => "C",
  400 => "CD",
  500 => "D",
  900 => "CM",
  1000 => "M"
}.freeze
SCALES =
[
  "hundreds-tens-ones",
  "thousand",
  "million",
  "billion",
  "trillion",
  "quadrillion",
  "quintillion",
  "sextillion",
  "septillion",
  "octillion",
  "nonillion",
  "decillion",
  "undecillion",
  "duodecillion",
  "tredecillion",
  "quattuordecillion",
  "quindecillion",
  "sexdecillion",
  "septemdecillion",
  "octodecillion",
  "novemdecillion",
  "vigintillion"
].freeze
DECIMAL_SLOTS =
[
  "tenths",
  "hundredths",
  "thousandths",
  "ten-thousandths",
  "hundred-thousandths",
  "millionths",
  "ten-millionths",
  "hundred-millionths",
  "billionths",
  "ten-billionths",
  "hundred-billionths",
  "trillionths",
  "quadrillionths",
  "quintillionths",
  "sextillionths",
  "septillionths",
  "octillionths",
  "nonillionths",
  "decillionths",
  "undecillionths",
  "duodecillionths",
  "tredecillionths",
  "quattuordecillionths",
  "quindecillionths",
  "sexdecillionths",
  "septemdecillionths",
  "octodecillionths",
  "novemdecillionths",
  "vigintillionths"
].freeze
CURRENCIES =
{
  eur: {
    unit: "euro",
    units: "euros",
    decimal_unit: "cent",
    decimal_units: "cents"
  },
  gbp: {
    unit: "pound",
    units: "pounds",
    decimal_unit: "pence",
    decimal_units: "pence",
  },
  jpy: {
    unit: "yen",
    units: "yen",
    decimal_unit: "sen",
    decimal_units: "sen",
  },
  pln: {
    unit: "zloty",
    units: "zlotys",
    decimal_unit: "grosz",
    decimal_units: "groszy"
  },
  usd: {
    unit: "dollar",
    units: "dollars",
    decimal_unit: "cent",
    decimal_units: "cents"
  }
}.freeze
VERSION =
"0.1.0"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize {|| ... } ⇒ Numeral

Create numeral with custom configuration

Yield Parameters:



243
244
245
246
247
248
# File 'lib/strings/numeral.rb', line 243

def initialize
  @configuration = Configuration.new
  if block_given?
    yield @configuration
  end
end

Class Method Details

.cardinaliseObject



214
215
216
# File 'lib/strings/numeral.rb', line 214

def cardinalize(num, **options)
  instance.cardinalize(num, **options)
end

.cardinalize(num, **options) ⇒ Object



211
212
213
# File 'lib/strings/numeral.rb', line 211

def cardinalize(num, **options)
  instance.cardinalize(num, **options)
end

.instanceObject



201
202
203
# File 'lib/strings/numeral.rb', line 201

def self.instance
  @instance ||= Numeral.new
end

.monetiseObject



228
229
230
# File 'lib/strings/numeral.rb', line 228

def monetize(num, **options)
  instance.monetize(num, **options)
end

.monetize(num, **options) ⇒ Object



225
226
227
# File 'lib/strings/numeral.rb', line 225

def monetize(num, **options)
  instance.monetize(num, **options)
end

.numeraliseObject



209
210
211
# File 'lib/strings/numeral.rb', line 209

def numeralize(num, **options)
  instance.numeralize(num, **options)
end

.numeralize(num, **options) ⇒ Object



206
207
208
# File 'lib/strings/numeral.rb', line 206

def numeralize(num, **options)
  instance.numeralize(num, **options)
end

.ordinaliseObject



219
220
221
# File 'lib/strings/numeral.rb', line 219

def ordinalize(num, **options)
  instance.ordinalize(num, **options)
end

.ordinalize(num, **options) ⇒ Object



216
217
218
# File 'lib/strings/numeral.rb', line 216

def ordinalize(num, **options)
  instance.ordinalize(num, **options)
end

.ordinalize_short(num) ⇒ Object



221
222
223
# File 'lib/strings/numeral.rb', line 221

def ordinalize_short(num)
  instance.ordinalize_short(num)
end

.romaniseObject



233
234
235
# File 'lib/strings/numeral.rb', line 233

def romanize(num)
  instance.romanize(num)
end

.romanize(num) ⇒ Object



230
231
232
# File 'lib/strings/numeral.rb', line 230

def romanize(num)
  instance.romanize(num)
end

Instance Method Details

#cardinalize(num, **options) ⇒ String Also known as: cardinalise

Convert a number to a cardinal numeral

Examples:

cardinalize(1234)
# => one thousand, two hundred thirty four

Parameters:

  • num (Numeric, String)

Returns:

  • (String)


276
277
278
# File 'lib/strings/numeral.rb', line 276

def cardinalize(num, **options)
  convert_numeral(num, **options)
end

#monetize(num, **options) ⇒ String Also known as: monetise

Convert a number into a monetary numeral

Examples:

monetize(123.45)
# => "one hundred twenty three dollars and forty five cents"

Parameters:

  • num (Numeric, String)

    the number to convert

Returns:

  • (String)


356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
# File 'lib/strings/numeral.rb', line 356

def monetize(num, **options)
  sep = options.fetch(:separator, @configuration.separator)
  curr_name = options.fetch(:currency, @configuration.currency)
  n = "%0.2f" % num.to_s
  decimals = (num.to_i.abs != num.to_f.abs)
  sentence = convert_numeral(n, **options.merge(trailing_zeros: true))
  dec_num = n.split(".")[1]
  curr = CURRENCIES[curr_name.to_s.downcase.to_sym]
  separators = [AND, POINT, sep].compact

  if decimals
    regex = /(\w+) (#{Regexp.union(separators)})/
    sentence.sub!(regex, "\\1 #{curr[:units]} \\2")
  else
    sentence += SPACE + (num.to_i == 1 ? curr[:unit] : curr[:units])
  end

  if decimals
    slots = Regexp.union(DECIMAL_SLOTS.map { |slot| slot.chomp('s') })
    regex = /(#{slots})s?/i
    suffix = dec_num.to_i == 1 ? curr[:decimal_unit] : curr[:decimal_units]
    if sentence.sub!(regex, suffix).nil?
      sentence += SPACE + suffix
    end
  end

  sentence
end

#numeralize(num, **options) ⇒ Object

Convert a number to a numeral

Parameters:

  • num (Numeric, String)

    the number to convert



256
257
258
259
260
261
262
263
# File 'lib/strings/numeral.rb', line 256

def numeralize(num, **options)
  case options.delete(:term)
  when /ord/
    ordinalize(num, **options)
  else
    cardinalize(num, **options)
  end
end

#ordinalize(num, **options) ⇒ String Also known as: ordinalise

Convert a number to an ordinal numeral

Examples:

ordinalize(1234)
# => one thousand, two hundred thirty fourth

ordinalize(12, short: true) # => 12th

Parameters:

  • num (Numeric, String)

    the number to convert

Returns:

  • (String)


295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/strings/numeral.rb', line 295

def ordinalize(num, **options)
  if options[:short]
    ordinalize_short(num)
  else
    decimals = (num.to_i.abs != num.to_f.abs)
    sentence = convert_numeral(num, **options)
    separators = [AND, POINT,
                  options.fetch(:separator, @configuration.separator)].compact

    if decimals && sentence =~ /(\w+) (#{Regexp.union(separators)})/
      last_digits = $1
      separator = $2
      replacement = CARDINAL_TO_ORDINAL[last_digits]
      pattern = /#{last_digits} #{separator}/
      suffix = "#{replacement} #{separator}"
    elsif sentence =~ /(\w+)$/
      last_digits = $1
      replacement = CARDINAL_TO_ORDINAL[last_digits]
      pattern = /#{last_digits}$/
      suffix = replacement
    end

    if replacement
      sentence.sub(pattern, suffix)
    else
      sentence
    end
  end
end

#ordinalize_short(num) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Convert a number to a short ordinal form

Examples:

ordinalize_short(123) # => 123rd

Parameters:

  • num (Numeric, String)

    the number to convert

Returns:

  • (String)


337
338
339
340
341
342
# File 'lib/strings/numeral.rb', line 337

def ordinalize_short(num)
  num_abs = num.to_i.abs

  num.to_i.to_s + (CARDINAL_TO_SHORT_ORDINAL[num_abs % 100] ||
    CARDINAL_TO_SHORT_ORDINAL[num_abs % 10])
end

#romanize(num) ⇒ String

Convert a number to a roman numeral

Examples:

romanize(2020) # => "MMXX"

Parameters:

  • num (Integer)

    the number to convert

Returns:

  • (String)


397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
# File 'lib/strings/numeral.rb', line 397

def romanize(num)
  n = num.to_i

  if n < 1 || n > 4999
    raise Error, "'#{n}' is out of range"
  end

  CARDINAL_TO_ROMAN.keys.reverse_each.reduce([]) do |word, card|
    while n >= card
      n -= card
      word << CARDINAL_TO_ROMAN[card]
    end
    word
  end.join
end