class Ziffern

Constants

FIRST_TWENTY

de.wikipedia.org/wiki/Zahlennamen

InvalidNumberError
LARGE_NUMBERS
TENS
TooLargeNumberError

Public Instance Methods

to_german(number) click to toggle source
# File ziffern.rb, line 67
def to_german(number)
  fail InvalidNumberError unless valid_number?(number)
  result = convert_sign(number) + convert_integer(number) + convert_decimals(number)
  result << "s" if number.to_s.end_with?("01") && !result.end_with?("s")
  result
end

Private Instance Methods

convert(number, one = "ein") click to toggle source
# File ziffern.rb, line 88
def convert(number, one = "ein")
  case number
  when 1             then one
  when 0..19         then FIRST_TWENTY[number]
  when 20..99        then twenty_to_99(number)
  when 100..999      then quantify_by_factor(100,  "hundert", number)
  when 1000..999_999 then quantify_by_factor(1000, "tausend", number)
  else convert_large_number(number)
  end
end
convert_decimals(number) click to toggle source
# File ziffern.rb, line 166
def convert_decimals(number)
  decimals = get_decimals_as_string(number)
  return "" if decimals.empty?

  " Komma " + convert_digits(decimals)
end
convert_digits(number) click to toggle source
# File ziffern.rb, line 177
def convert_digits(number)
  number.to_s.chars.map { |digit| convert_integer(digit) }.join(" ")
end
convert_integer(number) click to toggle source
# File ziffern.rb, line 84
def convert_integer(number)
  convert(number.to_i.abs, "eins")
end
convert_large_number(number) click to toggle source
# File ziffern.rb, line 118
def convert_large_number(number)
  number_of_millions, remainder = number.divmod(1000_000)

  text = convert_millions(number_of_millions)
  text << " " << convert_integer(remainder) unless remainder.zero?

  text
end
convert_millions(number_of_millions) click to toggle source
# File ziffern.rb, line 127
def convert_millions(number_of_millions)
  named_number_groups = slice_by_factor(number_of_millions, 1000)
  large_number_names  = large_number_names(named_number_groups.count)

  fail TooLargeNumberError if named_number_groups.size > LARGE_NUMBERS.size

  named_number_groups
    .zip(large_number_names)
    .reject { |amount, _| amount.zero? }
    .map    { |amount, name| quantify_big_name(amount, name) }
    .join(" ")
end
convert_sign(number) click to toggle source
# File ziffern.rb, line 80
def convert_sign(number)
  number.to_f < 0 ? "minus " : ""
end
get_decimals_as_string(number) click to toggle source
# File ziffern.rb, line 173
def get_decimals_as_string(number)
  number.to_s[/\.(\d+)/, 1].to_s
end
large_number_names(count) click to toggle source

large_number_names(3) => [“Billion”, “Milliarde”, “Million”]

# File ziffern.rb, line 162
def large_number_names(count)
  LARGE_NUMBERS.take(count).reverse
end
pluralize_big_name(amount, big_name) click to toggle source
# File ziffern.rb, line 144
def pluralize_big_name(amount, big_name)
  amount == 1 ? big_name : big_name.sub(/(e?)$/, "en")
end
quantify_big_name(amount, big_name) click to toggle source
# File ziffern.rb, line 140
def quantify_big_name(amount, big_name)
  [convert(amount, "eine"), pluralize_big_name(amount, big_name)].join(" ")
end
quantify_by_factor(factor, quantifier, number) click to toggle source
# File ziffern.rb, line 109
def quantify_by_factor(factor, quantifier, number)
  amount, remainder = number.divmod(factor)

  text = convert(amount) + quantifier
  text << convert(remainder) unless remainder.zero?

  text
end
slice_by_factor(number, factor) click to toggle source

slice_by_factor(12345678, 1000) => [12, 345, 678]

# File ziffern.rb, line 149
def slice_by_factor(number, factor)
  result    = []
  remainder = number

  until remainder.zero?
    remainder, slice = remainder.divmod(1000)
    result << slice
  end

  result.reverse
end
twenty_to_99(number) click to toggle source
# File ziffern.rb, line 99
def twenty_to_99(number)
  ten, remainder = number.divmod(10)

  if remainder.zero?
    TENS[ten]
  else
    "#{convert(remainder)}und#{TENS[ten]}"
  end
end
valid_number?(number) click to toggle source
# File ziffern.rb, line 76
def valid_number?(number)
  !!number.to_s[/\A-?\d+(\.\d+)?\z/]
end