How to convert numbers from 0 to 999,999,999,999,999 (up to 999 trillion) into English words in Ruby

1 Answer

0 votes
#
# Convert numbers to English words in Ruby
# ----------------------------------------
# Supports numbers from 0 to 999,999,999,999,999.
#
# Strategy:
# - Break the number into named groups: trillions, billions, millions,
#   thousands, hundreds.
# - Convert each 0–999 group using a helper method.
# - Append group names ("trillion", "billion", etc.) when needed.
# - Build the final string using an array and join() for efficiency.
#

ONES = [
  "zero", "one", "two", "three", "four",
  "five", "six", "seven", "eight", "nine",
  "ten", "eleven", "twelve", "thirteen", "fourteen",
  "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
].freeze

TENS_WORDS = [
  "", "", "twenty", "thirty", "forty",
  "fifty", "sixty", "seventy", "eighty", "ninety"
].freeze

#
# append_word:
# Adds a word to the output array.
#
def append_word(out, word)
  out << word unless word.empty?
end

#
# convert_hundreds:
# Converts numbers from 0 to 999 into words.
#
def convert_hundreds(n, out)
  return if n.zero?

  if n >= 100
    append_word(out, ONES[n / 100])
    append_word(out, "hundred")
    n %= 100
    append_word(out, "and") if n > 0
  end

  if n >= 20
    append_word(out, TENS_WORDS[n / 10])
    append_word(out, ONES[n % 10]) if n % 10 != 0
  elsif n > 0
    append_word(out, ONES[n])
  end
end

#
# number_to_words:
# Converts any number from 0 to 999,999,999,999,999 into English words.
#
def number_to_words(num)
  return "zero" if num.zero?

  out = []

  trillions = num / 1_000_000_000_000
  billions  = (num / 1_000_000_000) % 1000
  millions  = (num / 1_000_000) % 1000
  thousands = (num / 1_000) % 1000
  hundreds  = num % 1000

  if trillions > 0
    convert_hundreds(trillions, out)
    append_word(out, "trillion")
  end

  if billions > 0
    convert_hundreds(billions, out)
    append_word(out, "billion")
  end

  if millions > 0
    convert_hundreds(millions, out)
    append_word(out, "million")
  end

  if thousands > 0
    convert_hundreds(thousands, out)
    append_word(out, "thousand")
  end

  convert_hundreds(hundreds, out) if hundreds > 0

  out.join(" ")
end

#
# main:
# Demonstrates usage with multiple test numbers.
#
tests = [
  1_234,
  12_345,
  123_456,
  1_234_567,
  123_456_789,
  12_345_678_901,
  1_234_567_890_123,
  999_999_999_999_999
]

tests.each do |n|
  puts "#{n} -> #{number_to_words(n)}"
end



#
# run:
#
# 1234 -> one thousand two hundred and thirty four
# 12345 -> twelve thousand three hundred and forty five
# 123456 -> one hundred and twenty three thousand four hundred and fifty six
# 1234567 -> one million two hundred and thirty four thousand five hundred and sixty seven
# 123456789 -> one hundred and twenty three million four hundred and fifty six thousand seven hundred and eighty nine
# 12345678901 -> twelve billion three hundred and forty five million six hundred and seventy eight thousand nine hundred and one
# 1234567890123 -> one trillion two hundred and thirty four billion five hundred and sixty seven million eight hundred and ninety thousand one hundred and twenty three
# 999999999999999 -> nine hundred and ninety nine trillion nine hundred and ninety nine billion nine hundred and ninety nine million nine hundred and ninety nine thousand nine hundred and ninety nine
#

 



answered Sep 6 by avibootz

Related questions

...